2009-08-11 4 views

Antwort

39

Die Klammern ändern Sie den Kontext, in dem die grep aus Skalarkontext ausgewertet Kontext aufzulisten. Im skalaren Kontext gibt grep die Anzahl zurück, wie oft der Ausdruck wahr war. Im Listenkontext werden die Elemente zurückgegeben, für die der Ausdruck wahr war.

Folgende Highlights der Unterschied Kontext macht:

my $x = grep {/foo/} @array; # the number of things that match /foo/ 
my ($x) = grep {/foo/} @array; # the first thing that matches /foo/ 
my @foo = grep {/foo/} @array; # all the things that match /foo/ 
my (@foo) = grep {/foo/} @array; # all the things that match /foo/ 
+0

'scalar @ array' ist die Anzahl der Elemente in' @ array' –

1

grep eine Liste zurückgibt. Wenn Sie den Skalarvariablennamen in Klammern setzen, behandelt Perl den gesamten l-Wert als Liste, sodass er der Variablen den ersten Wert in der Liste zuweist.

Wenn Sie andere Skalare in den Klammern hatte, dann würden Sie die zweite bekommen, dritten, etc. Werte von grep ‚s return array in ihnen:

my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array; 
+3

grep gibt ein Array zurück. Aber nur im Array-Kontext. – innaM

+0

Und im skalaren Kontext gibt es die Anzahl der Wiederholungen der Übereinstimmung zurück, so dass es wirklich egal ist, wer das Array skaliert. – Plutor

+1

@Plutor: Die Dokumente sagen explizit, was 'grep' tut, daher gibt es keine Rechtfertigung für das Posten einer ungenauen Beschreibung. –

8

Die Klammern stellen eine list context für grep. grep gibt dann tatsächlich die Liste der Elemente zurück, für die der Ausdruck wahr war, und nicht nur die Anzahl, wie oft der Ausdruck wahr war.

+0

s/Array Kontext/Liste Kontext/ –

+0

Weise besser. Vielen Dank. – innaM

+0

Gern geschehen. –

7

Ich glaube, Sie suchen first_index von List::MoreUtils:

use List::MoreUtils qw(first_index); 

# ... 

my $index = first_index { $_ eq $search_for } @array; 
5

Die grep-Funktion verhält sich anders in Listenkontext und Skalarkontext. Diese in perldoc -f grep dokumentiert:

Wertet den Block oder EXPR für jedes Element von LIST (lokal $ _ an jedes Element gesetzt wird) und gibt den Listenwert bestehend aus diesen Elementen, für die der Ausdruck auf wahr bewertet. Gibt im skalaren Kontext an, wie oft der Ausdruck wahr war.

Sie können dies mit dem schlecht namens wantarray Funktion auf Ihrem eigenen Duplikat:

sub my_grep { 
    my $sub = shift; 
    my @return; 
    for my $item (@_) { 
     push @return if $sub->($item); 
    } 
    return @return if wantarray; 
    return scalar @return; 
} 
1

Außerdem glaube ich, grep nur die erste Instanz zu finden, ist ein wenig ineffizient, da es immer noch zu Fuß durch hat und führen Sie den Rückruf für jedes Element des Arrays. Besonders wenn Ihr Array lang ist, können Sie besser eine Schleife schreiben oder, wie oben erwähnt, List :: MoreUtils verwenden.