Perl: Хороший способ проверить, есть ли значение в массиве?

Если у меня есть массив:

@int_array = (7,101,80,22,42);

Как проверить, находится ли целочисленное значение 80 в массиве без прокрутки каждого элемента?

Ответ 1

Вы не можете без цикла. Эта часть того, что означает быть массивом. Вы можете использовать неявный цикл, используя grep или smartmatch, но есть еще цикл. Если вы хотите избежать цикла, используйте вместо него хэш (или дополнительно).

# grep
if ( grep $_ == 80, @int_array ) ...

# smartmatch
use 5.010001;
if ( 80 ~~ @int_array ) ...

Перед использованием smartmatch обратите внимание:

http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#The_smartmatch_family_of_features_are_now_experimental:

Семейство функций smartmatch теперь экспериментально

Интеллектуальное совпадение, добавленное в v5.10.0 и значительно переработанное в версии 5.10.1, является регулярной жалобой. Хотя есть несколько способов, в которых это полезно, он также оказался проблематичным и запутанным как для пользователей, так и для разработчиков Perl. Был предложен ряд предложений о том, как наилучшим образом решить эту проблему. Понятно, что smartmatch почти наверняка либо изменится, либо уйдет в будущем. Не рекомендуется полагаться на его текущее поведение.

Теперь предупреждения будут выдаваться, когда парсер увидит ~~, данный или когда. Чтобы отключить эти предупреждения, вы можете добавить эту строку в соответствующую область

Ответ 2

Решение CPAN: используйте List::MoreUtils

use List::MoreUtils qw{any}; 
print "found!\n" if any { $_ == 7 } (7,101,80,22,42);

Если вам нужно делать МНОГИЕ поисковые запросы в том же массиве, более эффективным способом является сохранение массива в хеш файле один раз и поиск в хеше:

@int_array{@int_array} = 1;
foreach my $lookup_value (@lookup_values) {
    print "found $lookup_value\n" if exists $int_array{$lookup_value}
}

Зачем использовать это решение по альтернативам?

  • Нельзя использовать интеллектуальное соответствие в Perl до 5.10. Согласно этому сообщению SO brian d foy] 2, интеллектуальное совпадение является коротким замыканием, поэтому оно подходит как "любое" решение для 5.10.

  • grep решение проходит через список целиком, даже если первый элемент из 1 000 000 длинного списка совпадает. any будет замыкаться на короткое замыкание и выйти из момента, когда будет найдено первое совпадение, тем самым он будет более эффективным. Оригинальный плакат явно сказал "без прокрутки через каждый элемент"

  • Если вам нужно делать LOT-запросы, одноразовая стоимость создания хэша делает метод поиска хэша более эффективным, чем любой другой. Подробнее см. этот SO-адрес

Ответ 3

Еще один способ проверить число в массиве:

#!/usr/bin/env perl

use strict;
use warnings;

use List::Util 'first';

my @int_array       = qw( 7 101 80 22 42 );
my $number_to_check = 80;

if ( first { $_ == $number_to_check } @int_array ) {
    print "$number_to_check exists in ", join ', ', @int_array;
}

См. List::Util.

Ответ 4

if ( grep /^80$/, @int_array ) {
    ...
}

Ответ 5

Если вы используете Perl 5.10 или новее, вы можете использовать smart match оператор ~~:

my $found = (80 ~~ $in_array);