Сравнение нескольких строк в Perl - PullRequest
8 голосов
/ 06 февраля 2012

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

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

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

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

Ответы [ 5 ]

14 голосов
/ 06 февраля 2012

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

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

Оператор ~~ выполняет умное совпадение между своими аргументами.

14 голосов
/ 06 февраля 2012

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

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

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

if (grep { $var eq $_ } qw{str1 str2 str3}) { … }
2 голосов
/ 07 февраля 2012
  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 .... Возможно, нет. Но List::MoreUtils::any заканчивается рано, и это более наглядно, чем идиома 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 :: Assemble , чтобы объединить список регулярных выражений в одно оптимизированное регулярное выражение.

1 голос
/ 17 июля 2015

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

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

if ($on_my_list{$var}) { ... }
0 голосов
/ 07 февраля 2012

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

use Quantum::Superpositions;

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

См. Также Тема Perl Monks

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...