Perl: Хороший способ проверить, есть ли значение в массиве? - PullRequest
14 голосов
/ 31 декабря 2010

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

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

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

Ответы [ 5 ]

31 голосов
/ 31 декабря 2010

Вы не можете без зацикливания.Это часть того, что значит быть массивом.Вы можете использовать неявный цикл, используя 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 и значительно пересмотренное в v5.10.1, было обычной жалобой.Хотя существует несколько способов его использования, он также оказался проблематичным и запутанным как для пользователей, так и для разработчиков Perl.Был целый ряд предложений о том, как наилучшим образом решить проблему.Понятно, что smartmatch почти наверняка либо изменится, либо исчезнет в будущем.Не рекомендуется полагаться на его текущее поведение.

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

7 голосов
/ 31 декабря 2010

Решение 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.Согласно этому посту, написанному Брайаном Д Фой] 2 , интеллектуальное совпадение - это короткое замыкание, поэтому оно так же хорошо, как «любое» решение для 5.10.

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

  • Если вам нужно выполнить МНОЖЕСТВО поисков, то единовременная неоправданная стоимость создания хеша делает метод поиска хешей МНОГО более эффективнымчем любой другой.Подробнее см. в этом сообщении

3 голосов
/ 31 декабря 2010

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

#!/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.

0 голосов
/ 31 декабря 2010

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

my $found = (80 ~~ $in_array);
0 голосов
/ 31 декабря 2010
if ( grep /^80$/, @int_array ) {
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...