2012-02-06 23 views
7

mam kod jak poniżej:Porównywanie wielu ciągów w Perl

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

Czy istnieje jakikolwiek celu optymalizacji tego. chcę coś takiego:

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

Jeśli przez "optymalizację" rozumie się "szybsze działanie", pierwsza wersja jest optymalna (jeśli zamówisz ciągi tak, aby były najbardziej prawdopodobne). – Mat

Odpowiedz

13

zależności od zawartości strun, regex jest bardzo wygodne:

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

W przeciwnym razie, można grep na listę:

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

dziękuję bardzo .. Pierwsze wyrażenie zadziałało, ale z usuniętymi nawiasami: if ($ var = ~/^ str1 | str2 | str3 $ /) – sundar

+5

@ user988967, Nie, to nie działa. Bez parensów będzie pasować do 'str1A',' Astr2A' i 'Astr3'. – ikegami

+0

@ikegami, tak, masz rację. dzięki ... Jeszcze jedno pytanie. Używam "use strict" u góry mojego kodu. więc radzisz mi użyć "?:" – sundar

14

W języku Perl 5.10 lub lepszym:

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

Operator ~~ wykonuje między swoimi argumentami smart match.

+1

+1; Nie miałem pojęcia, że ​​ten operator istnieje. –

+1

@MarceloCantos: *** "Operator smartmatch jest eksperymentalny, a jego zachowanie może ulec zmianie." *** Zalecam, aby go unikać – Borodin

+1

@Borodin: Generalnie unikam Perla, ale +1 do heads-upa. –

2
  1. Zastosowanie List::MoreUtils qw{any}

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

    To może być szybsze niż przy użyciu grep ponieważ List::MoreUtils::any wykończeń wcześnie, gdy stwierdzi mecz natomiast grep może zbudować kompletną listę meczów. Mówię "może", ponieważ Perl mógł zoptymalizować if (grep .... Może nie. Ale List::MoreUtils::any kończy się wcześniej i jest bardziej opisowy niż idiom if (grep ....

  2. Zrób skrót, który ma klucze do wszystkich ciągów chcesz dopasować

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

    Ma to tę wadę, że czas uruchamiania systemu oraz koszt pamięci używane do mieszania, ale przewagę jest to, że czas meczu jest bardziej podobny do O (log N). Więc jeśli masz dużo różnych wartości $var, które chcesz przetestować, może to być ogólnie lepsze.

  3. Zrób regex, który pasuje do wszystkich ciągów

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

    OK, więc jest to w porządku, jeśli struny są dosłownie qw{str1 str2 str3}, ale co jeśli to jest lista dowolnych ciągów?

    Można użyć Regexp::Assemble, aby połączyć listę wyrażeń regularnych w jedno zoptymalizowane wyrażenie regularne.

+0

[Regexp :: Assemble] (http://p3rl.org/Regexp::Assemble) nie jest potrzebny w nowszych Perlach, ponieważ regexps mają teraz [Trie optimization] (http://perldoc.perl.org/perl5100delta.html # Trie-optymalizacja-literowych-naprzemiennych-naprzemiennych). –

0

Jestem pół-żartem, ale będzie to zrobić:

use Quantum::Superpositions; 

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

Zobacz także tym Perl Monks thread

1

Aby uzyskać listę łańcuchów o stałej długości, konwersja listy do mieszania. Jest to szczególnie przydatne, jeśli zamierzasz sprawdzać listę kilka razy i jeśli lista się powiększy.

Powiązane problemy