2012-05-01 26 views
11

Tengo una matriz que contiene referance hash (es decir @AOH)ordenar una matriz de Hash de múltiples teclas Perl

$arr_ref = [ { 'brand' => 'A', 
       'supplier' => 'X', 
       'PO' => '2' 
       }, 
       { 'brand' => 'B', 
       'supplier' => 'Y', 
       'PO' => '1'  
       }, 
       { 'brand' => 'B', 
       'supplier' => 'X', 
       'PO' => '2'   
       }, 
       { 'brand' => 'A', 
       'supplier' => 'X', 
       'PO' => '1' 
       }, 
       { 'brand' => 'B', 
       'supplier' => 'X', 
       'PO' => '1'   
       } 
]; 

deseo aclarar que sobre la base de las tres teclas (es decir, marca, proveedor y PO) El orden de clasificación debe ser primero de marca, luego proveedor y luego finalmente en PO.

gama referance después de la clasificación debe ser:

$arr_ref = [ { 'brand' => 'A', 
       'supplier' => 'X', 
       'PO' => '1' 
       }, 
       { 'brand' => 'A', 
       'supplier' => 'X', 
       'PO' => '2' 
       }, 
       { 'brand' => 'B', 
       'supplier' => 'X', 
       'PO' => '1'   
       }, 
       { 'brand' => 'B', 
       'supplier' => 'X', 
       'PO' => '2'   
       },    
       { 'brand' => 'B', 
       'supplier' => 'Y', 
       'PO' => '1'  
       }, 
]; 

Respuesta

34

Desde <=> and cmp devuelven 0 para indicar la igualdad, y eso es falso, y porque los operadores booleanos lógicos de Perl devuelven el valor en lugar de sólo 0 o 1 de decidir, la clasificación por múltiples Keys es tan fácil como encadenar múltiples comparaciones junto con or o ||:

@$arr_ref = sort { $a->{brand} cmp $b->{brand} or 
        $a->{supplier} cmp $b->{supplier} or 
        $a->{PO}  <=> $b->{PO} 
       } @$arr_ref; 

estoy asumiendo que PO es un campo numérico, por lo que utilizar para <=> en lugar de cmp.

+0

Gracias CJM. Funcionó :-) –

+0

Simplemente agregando un escenario divertido. Tuve que asignar el valor de retorno del tipo {...} a una nueva matriz en lugar de usar la anterior (@ $ arr_ref). El primero devolvió una referencia vacía ... todavía no estoy seguro de por qué. Gracias – mhz

+0

Muy, muy útil, gracias! –

3

Lo siguiente debe ordenar la referencia de matriz y colocar la matriz de nuevo en el $arr_ref:

$arr_ref = [sort by_brand_supplier_PO @$arr_ref]; 

sub by_brand_supplier_PO { 
    $a->{brand} cmp $b->{brand} || 
    $a->{supplier} cmp $b->{supplier} || 
    $a->{PO} <=> $b->{PO} 
} 
+0

Gracias chicos. Funcionó :-) –

1

Puede utilizar Sort::Key::Multi, distribuido con Ordenar :: clave.

En este caso, estamos usando ssikeysort, que espera un bloque que devuelve una cadena, una cadena y un entero, y que ordena los valores por esa tupla. (Los s en ssi stands para cuerdas y la i de número entero.)

use Sort::Key::Multi qw(ssikeysort); 

@$arr_ref = ssikeysort { $_->{brand}, $_->{supplier}, $_->{PO} } @$arr_ref; 

También puede utilizar la variante en el lugar, que utiliza menos memoria:

use Sort::Key::Multi qw(ssikeysort_inplace); 

ssikeysort_inplace { $_->{brand}, $_->{supplier}, $_->{PO} } @$arr_ref; 
Cuestiones relacionadas