2011-10-17 71 views
9

我正在尋找一種很好的方法,首先按值排序哈希值,然後再按鍵。按值和鍵排序哈希(按此順序)

實施例:

my %userids = (
    williams => "Marketing", 
    smith => "Research", 
    johnson => "Research", 
    jones => "Marketing", 
    brown => "Marketing", 
    davis => "Research" 
); 

輸出:

Marketing: brown 
Marketing: jones 
Marketing: williams 
Research: davis 
Research: johnson 
Research: smith 

請注意,是第一個排序級別。第二個分類等級是密鑰。任何想法如何以優雅和高性能的方式做到這一點?謝謝!

回答

27

很好的參考:http://www.misc-perl-info.com/perl-sort.html#shv

#!/usr/bin/perl 

my %userids = (
    williams => "Marketing", 
    smith => "Research", 
    johnson => "Research", 
    jones => "Marketing", 
    brown => "Marketing", 
    davis => "Research" 
); 

foreach (sort { ($userids{$a} cmp $userids{$b}) || ($a cmp $b) } keys %userids) 
{ 
    print "$_: $userids{$_}\n"; 
} 
7

我想補充一點,在分揀使用\L sequence

Perlfaq4:如何對散列進行排序(可選擇使用值而不是鍵)?

爲了使我們的報表順序不區分大小寫,我們在雙引號字符串中使用\L sequence以使所有內容都爲小寫。 sort()塊然後比較小寫的值以確定按照何種順序放置鍵。

foreach (sort { $userids{$a} cmp $userids{$b} or "\L$a" cmp "\L$b") { 
    print "$_: $userids{$_}\n"; 
} 

輸出:

brown: Marketing 
jones: Marketing 
williams: Marketing 
davis: Research 
Johnson: Research # here 'J'ohnson, J is in uppercase(taking assumption), come as fifth record 
smith: Research 

2.

foreach (sort { $userids{$a} cmp $userids{$b} or $a cmp $b) { 
    print "$_: $userids{$_}\n"; 
} 

輸出:

brown: Marketing 
jones: Marketing 
williams: Marketing 
Johnson: Research # here it shifted to fourth record 
davis: Research 
smith: Research 
+0

我想說的語義,將_only_進入元素融入到哈希時意義。否則,當散列同時包含約翰遜和約翰遜時,你會得到莫名的結果。即在排序時,你幾乎不會去說'按鍵是等價的' - 按照傳統的定義,散列表不能包含兩個等效鍵 – sehe

+0

是的,這是真正的鍵總是在散列中是唯一的,從不包含兩個等效鍵,但你可以看到差異輸出。 –

+0

我可以看到輸出的差異。這就是爲什麼我認爲這將是一件奇怪的事情:它違反了我認爲的[最小驚喜原則](http://c2.com/cgi/wiki?PrincipleOfLeastAstonishment) – sehe