Ответ получен в ответ perlfaq4 на номер "How can I tell whether a certain element is contained in a list or array?".
Чтобы найти perlfaq, вы можете выполнить поиск по списку всех вопросов в perlfaq, используя ваш любимый браузер.
Из командной строки вы можете использовать ключ -q для perldoc для поиска ключевых слов. Вы бы нашли ответ на свой вопрос с помощью поиска «список»:
perldoc -q list
(части этого ответа, вносимого Anno Siegel и Брайан d Фой)
Услышав слово «в» является показателем что вы, вероятно, должны были использовать хэш, а не список или массив, чтобы хранить ваши данные. Хеши предназначены для быстрого и эффективного ответа на этот вопрос. Массивов нет.
Это, как говорится, есть несколько способов приблизиться к этому. В 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 ($ чтения, $ п, 1) является true для некоторого $ 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;
я не уверен, что я вижу проблемы зависимостей с List :: Util. Он стандартный с Perl, и если вы используете его с qw/first/(как это делал Draegtun), вы импортируете только одну подпрограмму. – Telemachus
Это не проблема сама по себе, это скорее личное предпочтение. – MaxVT
Проблема с зависимостью связана с ответом List :: Util. Если бы это был я, это был бы принятый ответ. Нежелание использовать основные модули поражает меня как предпочтение, основанное на суевериях. В этом случае grep {} почти так же хорош. – singingfish