2017-09-21 1 views
1

Meine Datenstruktur istPerl Art Hash von Hashes von der Third-Level-Taste und vergleichen es

my %hash = (
    firstkey => { 
       secondkey => { 
          2 => ['9','2'], 
          1 => ['3','4'], 
          3 => ['8','2'] 
       } 
      } 
); 

print Dumper \%hash; 

ich den Hash durch die drittens Schlüssel sortieren möchten. d.h. 1, 2 und 3 in diesem Fall und dann das zweite Element (index[1]) im Array vergleichen. Wenn sie gleich sind, und drucken Sie es dann aus.

Erwartet Sortiert Hash:

my %hash = (
    firstkey => { 
       secondkey => { 
          1 => ['3','4'], 
          2 => ['9','2'], 
          3 => ['8','2'] 
       } 
      } 
); 

print Dumper \%hash; 

Nach Art der Hash vergleichen wir die index[1] des ersten Array [3,4] mit dem zweiten Array [9,2]. 4 ist nicht gleich 2, also werden wir nichts drucken.

Dann vergleichen wir die index[1] des zweiten Array [9,2] mit dem dritten Array [4,2]. 2 gleich 2, dann werden wir alle den Inhalt davon

firstkey, secondkey, 3, [8,2]

wir nur die benachbarten Array vergleichen müssen drucken.

Ich lese viele Lösungen über das Sortieren des Hash, aber ich konnte keine Lösung finden, die es wirklich neu anordnet Ist es eine Möglichkeit, den Hash durch den Schlüssel neu anzuordnen und einen Hash mit der neuen Reihenfolge in Perl zu erstellen? Oder wir können den Hash nur mit der for-Schleife sortieren und in der for-Schleife vergleichen?

+5

Sie können nicht "_sort hash_" - sie sind intrinsisch ungeordnet. Aber Sie können eine sortierte Liste von Schlüsseln erhalten, indem Sie 'sort' auf der Liste der Hash-Schlüssel mit beliebigen Kriterien verwenden. Dann haben Sie eine _ordered_ Liste von Schlüsseln, die Sie durchlaufen müssen, damit Sie Ihren Hash "sortiert" verwenden können. Sehen Sie [diesen Beitrag] (https://stackoverflow.com/a/45338396/4653379) zum Sortieren eines ähnlichen Hashs oder [diesen Beitrag] (https://stackoverflow.com/a/45928281/4653379) für ein bisschen mehr involvierte Art mit einigen Kommentaren. Es gibt viel mehr da draußen. – zdim

+0

@ zdim Vielen Dank für Ihre Vorschläge. Ich versuche es. – Luke

+0

Während der obige Kommentar im Allgemeinen gut und notwendig ist, und es wert ist, durchzugehen, kann es in diesem Problem nicht helfen (und könnte so irreführend sein) - ich habe eine Antwort geschrieben. – zdim

Antwort

3

Man kann nicht einen „sortierten Hash“ hat – sie sind intrinsisch ungeordnete Datenstrukturen (siehe keys). Die Randomisierung des anfänglichen Seed- und Hash-Durchlaufs ist sogar enhanced for security purposes.

Aber wir können die Liste der Hash-Schlüssel nach Bedarf sortieren. Dann haben wir eine geordnete Liste, die durchlaufen werden kann und somit den Hash "sortiert" verarbeiten kann.

Die hier zu sortierenden Schlüssel befinden sich auf einer tieferen Ebene, also iterieren Sie über die oberen (zwei) Ebenen, um zu ihnen zu gelangen.Dann ist es eine einfache Art und Test

use warnings; 
use strict; 
use feature 'say'; 

my %hash = ( 
    firstkey1 => { 
     secondkey1 => { 
      2 => [9, 2], 1 => [3, 4], 3 => [8, 2] 
     } 
    } 
); 

foreach my $k1 (keys %hash) 
{ 
    foreach my $k2 (keys %{$hash{$k1}}) 
    { 
     # Relieve syntax below 
     my $hr = $hash{$k1}{$k2}; 

     my @sr_k3 = sort { $a <=> $b } keys %{$hr}; 

     foreach my $i (1..$#sr_k3) 
     { 
      if ($hr->{$sr_k3[$i]}[1] == $hr->{$sr_k3[$i-1]}[1]) 
      { 
       say "$k1, $k2, $sr_k3[$i], ", 
        '[', join(',', @{$hr->{$sr_k3[$i]}}), ']'; 
      } 
     } 
     #say "@{$hash{$k1}{$k2}{$_}}" for keys %{$hash{$k1}{$k2}}; 
    } 
} 

Ein paar Anmerkungen

  • Sortieren Tasten iteriert über beginnend mit dem zweiten aufgrund des Vergleichskriteriums

  • hashref bei kopiert die zweite Ebene nur für die Bequemlichkeit, um die chaotische Syntax zu entlasten

  • Wenn komplexe Datenstrukturen zu unhandlich bekommen kann es Zeit, um eine Klasse zu verwenden, anstatt

Dies ist für eine beliebige Anzahl von Tasten in beiden Ebenen funktioniert (nur ein Schlüssel für jede Ebene gezeigt).

+0

Ziemlich einfache und unkomplizierte Lösung. Danke für Ihre Hilfe – Luke

0

Wie bereits gesagt, können Sie die Reihenfolge des Hash nicht diktieren. Hier ist ein Weg, um es zu ordnen, was Sie sortieren können und den Vergleich, den Sie brauchen.

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my %hash = (firstkey => { 
       secondkey => { 
        2 => [9,2], 
        1 => [3,4], 
        3 => [8,2], 
       } 
      } 
     ); 


#obtain an array of two-element array refs, whose contents are the keys 
#for the "secondkey" hash and the corresponding value, respectively 

my @arr = map { [ $_, $hash{firstkey}->{secondkey}->{$_} ] } 
      keys %{$hash{firstkey}->{secondkey}}; 

#sort on the aforementioned key 

my @sorted = sort { $a->[0] <=> $b->[0] } @arr; 

#obtain an array of array refs, whose contents are a pair of adjacent 
#elements from the @sorted array 

my @ordered_pairs = map { [ $sorted[$_], $sorted[$_+1] ] } 
        (0 .. (scalar @sorted - 2)); 

#compare the elements in question, and do something if there's a match 

for (@ordered_pairs) { 
    if ($_->[0][1][1] == $_->[1][1][1]) { 
     print Dumper $_->[1]; 
    } 
} 
Verwandte Themen