2016-05-23 15 views
3

Wenn Sie Hashes verwenden, hat Perl das sehr handliche values-Schlüsselwort, um nur die Werte des Hash zu verarbeiten.Doppelte Hash-Werte in Perl

Sagen, ich habe einen doppelten Hash, das heißt etwa wie folgt erstellt:

my %dh = map { {$_->{id1}}{$_->{id2}} => $_ } @arr; 

values %dh Dann gibt ein Array von Hashes. Um die Werte zugreifen ich so etwas wie diese brauchen würde:

for my $key1 (keys %dh) { 
    for my $val (values %{ $dh{$key1} }) { 
     # stuff... 
    } 
} 

Gibt es einen besseren Weg, dies zu tun, zu vermeiden for Zyklen? So etwas wie values %{ values %dh }.

Entschuldigung für die schlechte Syntax, ich bin ziemlich neu in Perl.

+0

'map' und' keys' Ich schätze, aber ich habe gerade keine Tuits, um einen Testfall zu erstellen. – Quentin

Antwort

5

Sie können map erneut zum Extrahieren verwenden. Aber machen Sie sich keine Illusionen - es schleift immer noch. Es könnte allerdings elegantere sein:

for my $val (map { values %$_ } values %dh) { 
    #do stuff 
} 

Dies ist mehr oder weniger die gleiche Sache aber tun - es Ihre Hash ist Abflachen - immer die values von %dh - das eine Liste von Hash-Refs sein wird - und dann das Ziehen values von denen. (Ich denke, das sollte es tun, aber ohne Testdaten kann ich das nicht sicher sagen).

Hinweis - Die Rückgabe-Reihenfolge von values ist nicht definiert, so dass Sie sie in zufälliger Reihenfolge erhalten. Sie können die Bestellung über keys (und vielleicht sort) steuern, wenn Sie so geneigt sind.

Was map tut ist einfach einen Code-Block auszuwerten, und gibt die Ergebnisse als Liste zurück. Das ist, warum map { $_ => 1 } qw (one two three) funktioniert - es gibt tatsächlich ein Paar Werte zurück, die , wenn Sie es einem Hash zuweisen wird als Schlüssel-Wert-Paare behandelt.

use Data::Dumper; 

my @stuff = map { $_ => 1 } qw (one two three); 
print Dumper \@stuff; 
my %hash = map { $_ => 1 } qw (one two three); 
print Dumper \%hash; 

So - map kehrt 2 Werte hier, die Sie wie schreiben konnte:

my @stuff = map { $_, 1 } qw (one two three); 

Denn natürlich => ist wirklich nur ein Komma (mit einigen zusätzlichen Funktionen um zu zitieren).

Wenn Sie also eine Dereferenzierung eines Arrays durchführen, können Sie dasselbe tun - values gibt eine Liste der Werte von jedem Element in map zurück.

Aus Gründen der Klarheit:

use Data::Dumper; 
my @stuff = ([ 1, 2, 3 ], [4, 5, 6], [7, 8, 9]); 
print Dumper \@stuff; 
my @newstuff = map { @$_ } @stuff; 
print Dumper \@newstuff; 

im Wesentlichen die gleiche Sache zu tun - jeder der Hashreferenzen in @stuff durchqueren (weil das ist, wie mehrdimensionale Arrays in perl umgesetzt werden) und dann ‚auspackt‘ sie, die Ergebnisse zurückgeben.

+2

.. das Rindfleisch ist hier, dass Sie mehrere Werte aus dem Codeblock an die Karte übergeben können und sie werden in einen Strom von Werten aus Karte abgeflacht werden. –

+0

Das ist großartig, danke! –

Verwandte Themen