2011-08-18 49 views
3

我仍然在學習Perl,因此可能會有更高效的方法來實現這一點。我正在嘗試使用散列,將其顛倒$ value => $ keys,獲取新的鍵值(舊值),然後對這些鍵進行排序。顛倒散列,獲取密鑰和排序

這裏是有問題的代碼:

什麼我期待發生的是,反向%哈希將返回一個哈希類型,這正是關鍵是尋找。不過,我得到以下錯誤:

ARG類型1至密鑰必須散列(不反向)

我試圖把周圍的反向%哈希括號,但仍然得到了同樣的事情。

任何想法,爲什麼這不起作用?

回答

6

Perl函數可以返回標量值或列表;沒有顯式的散列返回類型 (您可以從子例程調用return %hash,但Perl會隱式地展開散列中的鍵值對並將它們作爲列表返回)。

因此,reverse %hash的返回值是一個列表,而不是散列,並且不適合用作keys的參數。您可以強制Perl解釋此列表與%{{}}投哈希:

foreach my $key (sort keys %{{reverse %hash}}) { ... 

你也可以排序說

foreach my $key (sort values %hash) { ... 

使用values %hash散列值是使用keys %{{reverse %hash}}微妙的不同因爲keys %{{reverse %hash}}不會返回任何重複的值。

+0

+1非重複的見解。 – TLP

+0

感謝您的回覆。這可能超出我的水平(我仍然在學習Perl 6th Ed的方法),但我可以在哪裏閱讀有關使用%{{}}的更多信息。可悲的是谷歌沒有這個詞的任何東西。 – dmux

+0

http://perldoc.perl.org/perlref.html在底部的「另請參見」部分還有一些鏈接。 – TLP

3

我想你準確描述的情況in this example

#!/usr/local/bin/perl 

use strict; 
use warnings; 

my %hash = (one => 1, two => 2, three => 3, four => 4); 

%hash = reverse %hash; 

foreach my $key (sort {$a <=> $b} keys %hash) { 
    print "$key=>$hash{$key}, "; 
} 
print "\n"; 

# it displays: 1=>one, 2=>two, 3=>three, 4=>four 
+0

感謝您的答覆。雖然這有效,但我更感興趣知道爲什麼我的發佈代碼沒有按預期行事。再次,謝謝! – dmux

+0

@chris,原因是您沒有將散列傳遞給'keys',就像錯誤消息所說的那樣。 – ikegami

4

keys的參數必須是一個散列,數組或表達式,而不是一個列表。如果你沒有

keys { reverse %hash } 

你會得到你期望的結果,因爲括號會創建一個匿名散列。另一方面,Parens只改變優先順序。或者,在這種情況下,它們可能被認爲與函數keys()有關,因爲大多數perl函數都有可選的parens。

此外,如果你只是想哈希值,你可以使用:

values %hash 

查看文檔reversevalueskeys獲取更多信息。

+0

感謝您的回覆。在發佈之前,我完全不理解在散列上使用反轉。從反向的perldoc頁面看,反轉顯示原始散列,然後構建一個新散列。但是,我仍然認爲這個新的散列將是反向的返回值。 我試着在反向和%哈希周圍添加括號,但仍然有同樣的問題。 – dmux

+0

我不知道你是否說你還有問題。 'reverse'返回* list *,而不是散列。一個列表基本上是'(1,2,3,4,5,6)',如果你試圖用'keys'來使用它,它會取第一個值'1',嘗試使用它,並放棄休息。 – TLP

+0

'{reverse%hash}'是對散列的引用,對於'keys'也不是一個合適的參數(我站得更正 - 你可以在Perl> = v5.14中使用散列引用) – mob

3

Pre 5.14,keys返回哈希鍵。這需要一個哈希。你沒有提供。 reverse不返回散列。實際上,只有標量才能返回,因此不可能返回散列。 (在內部,Perl可以直接在堆棧上放置哈希值,但這對用戶來說永遠不會看到,而不會導致「奇怪」的錯誤信息)。這個錯誤在編譯時被檢測到。

5。14更加靈活。它也將接受對散列的引用。 (它也會接受數組和數組的引用,但在這裏並不相關。)引用是標量,所以它們可以被函數返回。您的代碼實際上會使其運行時,但是無論您在標量上下文中返回什麼,都不會引用不存在的散列,因此您的代碼將在此時死亡。


您是否有理由希望顛倒散列?

foreach my $key (sort { $hash{$a} cmp $hash{$b} } keys %hash) { 
    my $val = $hash{$key}; 
    ... 
} 

如果你這樣做,

foreach my $val (sort keys %{ { reverse %hash } }) { 
    # No access to original key 
    ... 
} 

my %flipped = reverse %hash; 
foreach my $val (sort keys %flipped) { 
    my $key = $flipped{$val}; 
    ... 
}