Сравнение Нескольких Строк В Perl

у меня есть такой код:

if ( $var eq "str1" || $var eq "str2" || $var eq "str3" )
{
...
}

есть ли способы оптимизировать это. Я хочу что-то вроде:

if ( $var eq ["str1" || "str2" || "str3"] ) {...}

5 ответов


в зависимости от содержимого строк регулярное выражение довольно удобно:

if ($var =~ /^(str1|str2|str3)$/) { … }

в противном случае вы можете grep над списком:

if (grep { $var eq $_ } qw{str1 str2 str3}) { … }

в Perl 5.10 или лучше:

if ($var ~~ [qw( str1 str2 str3 )]) { ...} 

на ~~ оператор делает смарт-матч между ее аргументов.


  1. использовать List::MoreUtils qw{any}

    use List::MoreUtils qw{any};
    
    if ( any { $var eq $_ } 'str1', 'str2', 'str3' ) {
        ...
    }
    

    это может быть быстрее, чем при использовании grep, потому что List::MoreUtils::any заканчивается рано, когда он находит совпадение, а grep может создать полный список матчей. Я говорю "Может", потому что Perl может предположительно оптимизировать if (grep .... А может, и нет. Но!--5--> заканчивает рано, и это более описательно, чем if (grep ... идиома.

  2. сделайте хэш, который имеет ключи всех строк, которые вы хотите матч

    my %matcher;
    
    @matcher{qw{str1 str2 str3}} = ();
    
    if ( exists $matcher{$var} ) {
        ...
    }
    

    это имеет недостаток времени настройки и стоимости памяти, используемой для хэша, но преимущество в том, что время совпадения больше похоже на O(log N). Поэтому, если у вас много разных значений $var что вы хотите проверить, то это может быть быстрее в целом.

  3. сделайте регулярное выражение, которое соответствует всем вашим строкам

    if ( $var =~ m/^str[123]$/so ) {
        ...
    }
    

    хорошо, так что это нормально, если ваши строки буквально qw{str1 str2 str3}, а что, если это список произвольные строки?

    вы могли бы использовать Regexp:: Собрать объединить список регулярных выражений в одно оптимизированное регулярное выражение.


для списка фиксированных строк преобразуйте свой список в хэш. Это особенно полезно, если вы собираетесь проверить свой список несколько раз, и если ваш список становится больше.

%on_my_list = map {; $_ => 1 } 'str1', 'str2', 'str3', ...;

if ($on_my_list{$var}) { ... }

я полушутя, но это сделает это:

use Quantum::Superpositions;

if ($x == any($a, $b, $c)) { ...  }

см. также Perl монахи нить