2010-08-27 8 views
6

que tienen un hash de hashes, así:¿Cómo puedo mapear (y clasificar) los valores de un hash de hashes?

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

que desea extraer el elemento "b" y ponerlo en una matriz. En este momento, estoy haciendo un bucle a través del hash para hacer esto, pero creo que puedo mejorar la eficiencia ligeramente usando el mapa en su lugar. Estoy bastante seguro de que si se trataba de un conjunto de valores hash, que haría uso de algo como esto:

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

Perdóname si estoy equivocado, todavía estoy aprendiendo cómo funciona mapa. Pero lo que me gustaría saber es cómo haría para mapear el hash de los hashes. ¿Es esto posible utilizando el mapa? Todavía tengo que encontrar algún ejemplo de hacer esto.

Aún mejor, el siguiente paso en este código es ordenar la matriz una vez que se haya rellenado. Estoy bastante seguro de que esto es posible, pero no soy lo suficientemente inteligente como para usar el mapa para resolverlo yo mismo. ¿Cómo podría hacer esto todo de una vez?

Gracias. Seth

Respuesta

11

Este extractos y clasifica todos "b" s:

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

Eso funcionó muy bien, exactamente lo que estaba buscando. Reemplacé 26 líneas de código con esta, y mejoré el rendimiento de esa función de aproximadamente O (n) a O (1). ¡Gracias! – sgsax

+1

Bueno, todavía tiene que recorrer los valores del hash y ordenarlos, por lo que en realidad no es O (1). – Corey

1

Tome la segunda solución, y sustituir values %hash para @hasharray:

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

(. Y no se olvide el ; para terminar la declaración)

3

Esto completa @array con una lista ordenada de referencias de matriz, cada que contiene el valor de b y el hashref del que proviene.

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

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

'$ a -> [0]' es más fácil de leer que '$$ a [0]'; del mismo modo '$ _-> {b}' en lugar de '$$ _ {b}'. –

+0

Es mejor usar el operador '<=>' en lugar de 'cmp' al ordenar los números. –

+0

@eugene => buen punto, fijación. @Philip => Prefiero los sigilos doblados por dos razones. En primer lugar, se cumple con otras formas de desreferenciación como '@ $ a [1, 2]'. En segundo lugar, el operador '->' se usa para llamadas a métodos, por lo que prefiero usarlo solo en situaciones donde se invoca el código. –

Cuestiones relacionadas