2010-08-27 11 views
6

Ho un hash di hash, in questo modo:Come mappare (e ordinare) i valori da un hash di hash?

 
%hash = (a => { b => 1, c =>2, d => 3}, 
      a1 => { b => 11, c =>12, d => 13}, 
      a2 => { b => 21, c =>22, d => 23}) 

Voglio estrarre l'elemento "b" e metterlo in un array. In questo momento, eseguo il ciclo dell'hash per farlo, ma penso di poter migliorare leggermente l'efficienza utilizzando invece la mappa. Sono abbastanza sicuro che se questo era un array di hash, userei qualcosa di simile:

 
@hasharray = ({ b => 1, c =>2, d => 3}, 
       { b => 11, c =>12, d => 13}, 
       { b => 21, c =>22, d => 23}) 
@array = map { ($_->{b} => $_) } @hasharray 

Perdonami se mi sbaglio, sto ancora imparando come funziona mappa. Ma quello che mi piacerebbe sapere è come farei per mappare l'hash degli hash? Questo è possibile anche usando la mappa? Devo ancora trovare qualche esempio per farlo.

Ancora meglio, il passaggio successivo in questo codice consiste nell'ordinare l'array una volta popolato. Sono abbastanza sicuro che sia possibile, ma non sono abbastanza intelligente nell'usare la mappa per capirlo da solo. Come faccio a fare tutto questo in un colpo solo?

Grazie. Seth

risposta

11

Questo estratti e ordina tutto "b" s:

my @array = sort { $a <=> $b } map $_->{b}, values %hash; 
+0

Ha funzionato alla perfezione, esattamente quello che stavo cercando. Ho sostituito 26 linee di codice con questo e ho migliorato le prestazioni di quella funzione da circa O (n) a O (1). Grazie! – sgsax

+1

Bene, deve ancora scorrere i valori dell'hash e ordinarli, quindi in realtà non è O (1). – Corey

1

Prendete la vostra seconda soluzione, e sostituire values %hash per @hasharray:

@array = map { ($_->{b} => $_) } values %hash; 

(. E non dimenticate il ; di interrompere l'informativa)

3

Questo riempie @array con un elenco ordinato di riferimenti di matrice, ciascuno contenente il valore di b e l'hashref da cui proviene.

my @array = sort {$$a[0] <=> $$b[0]} 
      map { [$$_{b} => $_] } 
      values %hash; 

my @sorted_hashes = map {$$_[1]} @array; 
+1

'$ a -> [0]' è più facile da leggere di '$$ a [0]'; allo stesso modo '$ _-> {b}' piuttosto che '$$ _ {b}'. –

+0

È preferibile utilizzare l'operatore '<=>' invece di 'cmp' quando si ordinano i numeri. –

+0

@eugene => buon punto, correzione. @Philip => Preferisco i sigilli raddoppiati per due motivi. Per prima cosa, si regge con altre forme di dereferenziazione come '@ $ a [1, 2]'. Secondo, l'operatore '->' viene usato per le chiamate al metodo, quindi preferisco usarlo solo nelle situazioni in cui viene chiamato il codice. –

Problemi correlati