2012-05-01 34 views
11

Mam Referance tablicę zawierającą hashe (tj @AOH)Sortowanie tablicę Hash przez wielu kluczy 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'   
       } 
]; 

chcę rozwiązać to na podstawie wszystkich trzech przycisków (tj marki, dostawcy i PO). Porządek sortowania powinien być najpierw marką, następnie dostawcą, a następnie ostatecznie PO.

tablica Referance po sortowaniu powinny być:

$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'  
       }, 
]; 

Odpowiedz

34

Od <=> and cmp return 0 do wskazania równości, i to jest fałszywe, a ponieważ logiczne operatory logiczne Perla powrócić decydującym wartość zamiast tylko 0 lub 1, sortując wielokrotności klawisze jest tak proste jak sznurka wielokrotnych porównań wraz z or lub ||:

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

jestem przy założeniu, że pO jest pole numeryczne, więc użyć <=> dla to zamiast cmp.

+0

dziękuję CJM. To zadziałało :-) –

+0

Po prostu dodajemy scenariusz zabawnego przypadku. Musiałem przypisać zwracaną wartość sortowania {...} do nowej tablicy zamiast starej (@ $ arr_ref). Ten pierwszy zwrócił puste odniesienie ... wciąż nie wiem dlaczego. Dzięki – mhz

+0

Bardzo, bardzo przydatne, dziękuję! –

3

Poniższa należy posortować odniesienie tablicy i umieścić tablicę z powrotem do $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

Dziękuję wam. Zadziałało :-) –

1

Można użyć Sort::Key::Multi, rozprowadzane Sortuj :: Klucz.

W tym przypadku używamy ssikeysort, który oczekuje bloku, który zwraca ciąg, ciąg i liczbę całkowitą, i który sortuje wartości przez tę krotkę. (The s w ssi oznacza ciąg i i do liczby całkowitej.)

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

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

Można również skorzystać z wariantu w miejscu, które zużywa mniej pamięci:

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

ssikeysort_inplace { $_->{brand}, $_->{supplier}, $_->{PO} } @$arr_ref; 
Powiązane problemy