2011-08-19 12 views
5

Credo che questo sia il modo che normalmente ordinare un hash per valore:Ordinamento un hash per valore, quando ha molte chiavi

foreach my $key (sort { $hash{$a} <=> $hash{$b} } (keys %hash)) { 
    print "$key=>$hash{$key}"; 
} 

Questo sarebbe stampare i valori piccolo al più grande.

Ora, che cosa se ho un hash come questo:

$hash{$somekey}{$somekey2}{$thirdkey} 

Come potrei ordina per valori e ottenere tutte le chiavi come bene?

+0

Quindi vuoi ordinare in modo irregolare la profondità all'interno della struttura? – DavidO

+0

In questo hash c'è una profondità fissa di 3 tasti e voglio ordinare l'hash in base al valore di tutte le terzine di chiavi esistenti. – petranaya

risposta

3

vorrei solo creare un nuovo hash:

my %new; 
for my $k1 (keys %hash) { 
    for my $k2 (keys %{$hash{$k1}}) { 
    for my $k3 (keys %{$hash{$k1}{$k2}}) { 
     $new{$k1,$k2,$k3} = $hash{$k1}{$k2}{$k3}; 
    } 
    } 
} 

my @ordered = sort { $new{$a} <=> $new{$b} } keys %new; 
for my $k (@ordered) { 
    my @keys = split($;, $k); 
    print "key: @k  - value: $new{$k}\n"; 
} 
+0

Grazie, ho appena finito di usare questo. – petranaya

+2

Attenzione che '$;' deve essere un valore che * non appare mai nelle tue chiavi * (per default è "\ x1c", un carattere di controllo), altrimenti questo codice si bloccherà e brucerà. – hobbs

+0

@ FMc - grazie! post corretto. – ErikR

1

Ecco un modo per farlo utilizzando Deep::Hash::Utils.

use Deep::Hash::Utils qw(slurp); 

my %h = (
    A => { 
     Aa => { Aaa => 4, Aab => 5 }, 
     Ab => { Aba => 1 }, 
     Ac => { Aca => 2, Acb => 9, Acc => 0 }, 
    }, 
    B => { 
     Ba => { Baa => 44, Bab => -55 }, 
     Bc => { Bca => 22, Bcb => 99, Bcc => 100 }, 
    }, 
); 

my @all_keys_and_vals = slurp \%h; 
print "@$_\n" for sort { $a->[-1] <=> $b->[-1] } @all_keys_and_vals; 

uscita:

B Ba Bab -55 
A Ac Acc 0 
A Ab Aba 1 
A Ac Aca 2 
A Aa Aaa 4 
A Aa Aab 5 
A Ac Acb 9 
B Bc Bca 22 
B Ba Baa 44 
B Bc Bcb 99 
B Bc Bcc 100 
1

ho fatto qualcosa di simile spostando un di riferimento fino al tasto cancelletto appropriata. È quindi possibile eseguire l'ordinamento sul puntatore.

Il vantaggio di farlo in questo modo è che è facile da regolare se il livello cambia.

Ciò che ho usato per questa metodologia è spostare sistematicamente il puntatore su un livello specifico facendo riferimento a un array di chiavi. (Es: my @Keys = ('Value', 'Value2');)

Credo che un derivato dell'esempio seguente possa darti quello che stai cercando.

my $list_ref; 
my $pointer; 

my %list = (
    Value => { 
     Value2 => { 
     A => '1', 
     C => '3', 
     B => '2', 
     }, 
    }, 
); 

$list_ref = \%list; 
$pointer = $list_ref->{Value}->{Value2}; 

foreach my $key (sort { $pointer->{$a} <=> $pointer->{$b} } (keys %{$pointer})) { 
    print "Key: $key\n"; 
} 
1

per scopi accademici, ecco una abbastanza ordinata funzione ricorsiva:

sub flatten_hash { 
    my ($hash, $path) = @_; 
    $path = [] unless defined $path; 

    my @ret; 

    while (my ($key, $value) = each %$hash) { 
    if (ref $value eq 'HASH') { 
     push @ret, flatten_hash($value, [ @$path, $key ]); 
    } else { 
     push @ret, [ [ @$path, $key ], $value ]; 
    } 
    } 

    return @ret; 
} 

che prende un hash come

{ 
    roman => { 
     i => 1, 
     ii => 2, 
     iii => 3, 
    }, 
    english => { 
     one => 1, 
     two => 2, 
     three => 3, 
    }, 
} 

e lo trasforma in una lista come

(
    [ ['roman','i'], 1 ], 
    [ ['roman', 'ii'], 2 ], 
    [ ['roman', 'iii'], 3 ], 
    [ ['english', 'one'], 1 ], 
    [ ['english', 'two'], 2 ], 
    [ ['english', 'three'], 3 ] 
) 

anche se ovviamente t l'ordine è destinato a variare. Dato questo elenco, è possibile ordinarlo su { $a->[1] <=> $b->[1] } o simile e quindi estrarre il percorso chiave da @{ $entry->[0] } per ciascuna voce. Funziona indipendentemente dalla profondità della struttura dei dati e anche se i nodi foglia non si verificano tutti alla stessa profondità. Ha bisogno di un po 'di estensione per gestire strutture che non sono puramente di hashref e scalari semplici, però.

Problemi correlati