Wie funktioniert dieses Perl grep, um die Vereinigung mehrerer Hashes zu bestimmen?

7

Ich verstehe die letzte Zeile dieser Funktion nicht von Programming Perl 3e .

So können Sie eine Funktion schreiben, die eine Art Schnittmenge erstellt, indem Sie eine Liste von Schlüsseln zurückgibt, die in allen an sie übergebenen Hashes vorkommen:

@common = inter( \%foo, \%bar, \%joe );
sub inter {
    my %seen;
    for my $href (@_) {
        while (my $k = each %$href) {
            $seen{$k}++;
        }
    }
    return grep { $seen{$_} == @_ } keys %seen;
}

Ich verstehe, dass %seen ein Hash ist, der jeden Schlüssel der Anzahl der Male zuordnet, in denen er in einem der Hashes gefunden wurde, die der Funktion zur Verfügung gestellt wurden.

    
titaniumdecoy 15.04.2010, 05:10
quelle

3 Antworten

16

grep nimmt eine Liste an, die an sie übergeben wird (in diesem Fall wird jedes Element in einem beliebigen von die Hashrefs); und geben Sie eine Liste nur der Elemente zurück, deren Ausdruck im Block wahr ist (indem Sie $_ variable lokal auf jedes Element in der Liste setzen).

Schauen wir uns an, wie dieser Ausdruck ausgewertet wird:

  • @_ ist ein Array aller an die Subroutine übergebenen Parameter - in unserem Fall wurde eine Liste von Hash-Referenzen übergeben.

  • In $seen{$_} == @_ Ausdruck wird diese Liste in einen skalaren Kontext gezwungen (aufgrund von == ).

  • Bei Verwendung in einem skalaren Kontext wird eine Liste mit der Anzahl der Elemente in einer Liste ausgewertet - im obigen Beispiel mit 3, da 3 Hashrefs übergeben wurden.

Also für jeden Schlüssel in %seen (z.B. jeder Schlüssel, der in irgendeinem der N Hash-Referenzen zu sehen ist); Der Ausdruck $seen{$_} == @_ vergleicht numerisch die Anzahl der Male, die das Element in den Hashes gesehen wurde, mit der Gesamtzahl der Hashes - es ist natürlich nur dann gleich, wenn das Element in ALLEN Hashes ist, die übergeben wurden, und also ein Mitglied der Kreuzung, die wir wollen.

Um die Analyse zusammenzufassen, gibt grep eine Liste aller Schlüssel zurück, die in JEDEM Hash vorkommen (auch N mal vorkommen, wenn N die Anzahl der Hashes ist). Z.B. eine Kreuzung.

    
DVK 15.04.2010, 05:14
quelle
3
%Vor%

Dies wird nacheinander auf jedes Element der Liste angewendet, das Element wird als $ _ aliasiert. Wenn der Block den Wert true zurückgibt, wird das Element zum zurückgegebenen Array hinzugefügt.

in diesem Fall:

%Vor%

Der Block ist $seen{$_} == @_ , der den Wert des gesehenen Hashs mit @_ vergleicht. @_ wird im skalaren Kontext ausgewertet und gibt somit die Anzahl der Elemente im Array @_ zurück. @_ repräsentiert die Argumente für die aktuelle Funktion. In diesem Fall ( \%foo, \%bar, \%joe ) , das 3 im skalaren Kontext zurückgibt. Unsere Liste ist keys %seen , was ein Array ist, das alle in %seen vorhandenen Schlüssel enthält.

äquivalente englische Aussagen:

  • "gib mir eine Liste aller Schlüssel von %seen wo der Wert zugeordnet ist dieser Schlüssel ist gleich der Anzahl von Elemente, die an diese Funktion übergeben wurden "
  • "gib mir eine Liste aller Schlüssel von %seen wo der Wert zugeordnet ist Dieser Schlüssel ist 3 "
  • "gib mir eine Liste von alle Schlüssel von %seen , die haben Wert 3 , dh alle Schlüssel von %seen das sind in jedem der 3 vorhanden an diese Funktion übergebene HashRefs "
spazm 15.04.2010 05:37
quelle
2

Der Zweck der Funktion besteht darin, die Elemente zu finden, die in allen an sie übergebenen Hashes erscheinen.

Die letzte Zeile grep s die von keys %seen zurückgegebene Liste. Um zu ermitteln, ob ein bestimmter Schlüssel in allen Hashwerten vorhanden ist, die an die Funktion übergeben wurden, können wir den Wert dieses Schlüssels in %seen mit der Anzahl der Argumente für inter vergleichen.

Im Block grep wird $_ auf jedes Element der Liste keys gesetzt und auf eine Bedingung getestet.

Ein Array im Skalarkontext berechnet seine Länge. @_ ist das Array von Argumenten, die an die Subroutine übergeben werden. Und der Operator == setzt seine Operanden in einen skalaren Kontext, so dass wir einfach den Wert von $seen{$_} mit der Länge @_ vergleichen können. Wenn sie gleich sind, dann erschien dieser Schlüssel in allen Hashes.

    
friedo 15.04.2010 05:24
quelle

Tags und Links