Ответ на этот вопрос содержится в ответе perlfaq4 на "Как определить, содержится ли определенный элемент в списке или массиве?".
Чтобы найти perlfaq, вы можете выполнить поиск по списку всех вопросов в perlfaq, используя ваш любимый браузер.
В командной строке вы можете использовать ключ -q для perldoc для поиска ключевых слов. Вы бы нашли свой ответ, выполнив поиск «список»:
perldoc -q list
(части этого ответа предоставлены Anno Siegel и brian d foy)
Услышав слово «в», вы, вероятно, должны были использовать хэш, а не список или массив, для хранения ваших данных. Хэши предназначены для быстрого и эффективного ответа на этот вопрос. Массивы - нет.
При этом есть несколько подходов к этому. В Perl 5.10 и более поздних версиях вы можете использовать оператор интеллектуального сопоставления, чтобы проверить, содержится ли элемент в массиве или хэше:
use 5.010;
if( $item ~~ @array )
{
say "The array contains $item"
}
if( $item ~~ %hash )
{
say "The hash contains $item"
}
С более ранними версиями Perl вам придется проделать немного больше работы. Если вы собираетесь делать этот запрос много раз для произвольных строковых значений, самым быстрым способом, вероятно, будет инвертировать исходный массив и поддерживать хэш, ключи которого являются значениями первого массива:
@blues = qw/azure cerulean teal turquoise lapis-lazuli/;
%is_blue = ();
for (@blues) { $is_blue{$_} = 1 }
Теперь вы можете проверить, является ли $is_blue{$some_color}. Возможно, было бы хорошей идеей сохранить блюз в мешанине.
Если все значения представляют собой небольшие целые числа, вы можете использовать простой индексированный массив. Такой массив займет меньше места:
@primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
@is_tiny_prime = ();
for (@primes) { $is_tiny_prime[$_] = 1 }
# or simply @istiny_prime[@primes] = (1) x @primes;
Теперь вы проверяете, является ли $is_tiny_prime[$some_number].
Если рассматриваемые значения являются целыми числами, а не строками, вы можете сэкономить довольно много места, используя вместо этого битовые строки:
@articles = ( 1..10, 150..2000, 2017 );
undef $read;
for (@articles) { vec($read,$_,1) = 1 }
Теперь проверьте, верно ли vec($read,$n,1) для некоторого $n.
Эти методы гарантируют быстрое выполнение отдельных тестов, но требуют реорганизации исходного списка или массива. Они окупаются только в том случае, если вам нужно проверить несколько значений на одном и том же массиве.
Если вы тестируете только один раз, стандартный модуль List::Util сначала экспортирует функцию для этой цели. Он работает, останавливаясь, как только находит элемент. Для скорости она написана на C, а ее эквивалент на Perl выглядит так:
sub first (&@) {
my $code = shift;
foreach (@_) {
return $_ if &{$code}();
}
undef;
}
Если скорость не имеет большого значения, распространенная идиома использует grep в скалярном контексте (который возвращает количество элементов, которые прошли его условие) для обхода всего списка. Тем не менее, это имеет то преимущество, что сообщает вам, сколько совпадений было найдено.
my $is_there = grep $_ eq $whatever, @array;
Если вы действительно хотите извлечь совпадающие элементы, просто используйте grep в контексте списка.
my @matches = grep $_ eq $whatever, @array;
person
brian d foy
schedule
06.04.2009