2012-05-01 32 views
11

Tôi có một referance mảng chứa băm (tức @AOH)Sorting một mảng của Hash bởi nhiều phím 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'   
       } 
]; 

Tôi muốn sắp xếp nó trên cơ sở của tất cả ba phím (ví dụ: thương hiệu, nhà cung cấp và PO). Thứ tự sắp xếp phải là thương hiệu đầu tiên, sau đó là nhà cung cấp và sau đó cuối cùng là PO.

mảng referance sau khi phân loại nên là:

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

Trả lời

34

Kể từ <=> and cmp return 0 để chỉ ra sự bình đẳng, và đó là sai sự thật, và bởi vì các nhà khai thác Boolean logic của Perl trả về giá trị thay vì chỉ 0 hoặc 1 quyết định, sắp xếp theo nhiều phím là dễ dàng như việc xâu chuỗi nhiều sự so sánh cùng với or hoặc ||:

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

tôi giả định rằng PO là một trường số, vì vậy bạn sử dụng <=> cho thay vì cmp.

+0

Cảm ơn bạn CJM. Nó hoạt động :-) –

+0

Chỉ cần thêm một trường hợp hài hước. Tôi đã phải gán giá trị trả về của loại {...} cho mảng mới thay vì sử dụng giá trị cũ (@ $ arr_ref). Nguyên tắc trả về trống rỗng cũ ... vẫn không chắc tại sao. Cảm ơn – mhz

+0

Rất rất hữu ích, cảm ơn bạn! –

3

Sau đây nên sắp xếp các tài liệu tham khảo mảng và đặt mảng trở lại vào $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

Cảm ơn các bạn. Nó đã làm việc :-) –

1

Bạn có thể sử dụng Sort::Key::Multi, phân phối với Sắp xếp :: Key.

Trong trường hợp này, chúng tôi đang sử dụng ssikeysort, dự kiến ​​một khối trả về một chuỗi, một chuỗi và một số nguyên và sắp xếp các giá trị theo bộ tuple đó. (Các s trong ssi đứng cho chuỗi và i cho số nguyên.)

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

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

Bạn cũng có thể sử dụng các biến thể tại chỗ, trong đó sử dụng ít bộ nhớ:

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

ssikeysort_inplace { $_->{brand}, $_->{supplier}, $_->{PO} } @$arr_ref; 
Các vấn đề liên quan