2012-12-04 34 views
1

我有一個散列,我按值最大到最小排序。我將如何去取得前五名?在這裏有一篇文章談到只有一個價值。如何從值散列獲得頂部鍵

What is the easiest way to get a key with the highest value from a hash in Perl?

我明白,所以纔會讓說,讓這些價值觀並重新加入到一個數組並刪除哈希元素,然後執行過程?

似乎應該有一個更簡單的方法來做到這一點,然而。

我的散列稱爲%字。

已編輯已將代碼視爲已回答的問題,而無需真正需要它。

+0

向我們顯示您的代碼。 – edem

+3

''我有一個散列,我排序..「否。你不能排序散列。 – TLP

+0

不,你不能,我的意思是我按順序打印它們,但是我想以最高的價值獲得前五名。 –

回答

5

你的問題是如何從你的散列中獲得五個最高值。你有這樣的代碼:

my @keys = sort { 
    $words{$b} <=> $words{$a} 
    or 
    "\L$a" cmp "\L$b" 
} keys %words; 

你有你的排序哈希鍵。從那裏拿五個頂級鑰匙?

my @highest = splice @keys, 0, 5; # also deletes the keys from the array 
my @highest = @keys[0..4];   # non-destructive solution 

也在你的代碼的一些意見:

open(my $filehandle0, '<', $file0) || die "Could not open $file0\n"; 

這是一個好主意,包括在模具的語句錯誤消息$!以獲取爲什麼打開失敗的有價值的信息。

for (@words) { 
    s/[\,|\.|\!|\?|\:|\;|\"]//g; 
} 

就像我在評論中所說的,你不需要轉義字符或在字符類括號中使用替代。使用其中之一:

s/[,.!?:;"]//g for @words; #or 
tr/,.!?:;"//d for @words; 

接下來的部分有點奇怪。

my @stopwords; 
while (my $line = <$filehandle1>) { 
    chomp $line; 
    my @linearray = split(" ", $line); 
    push(@stopwords, @linearray); 
} 
for my $w (my @stopwords) { 
    s/\b\Q$w\E\B//ig; 
} 

您閱讀從文件中禁用詞...然後你從$_刪除禁用詞?你在這一點上甚至使用$_?此外,您在循環頭文件中重新聲明@stopwords數組,這實際上意味着您的新數組將爲空,並且您的循環將永遠不會運行。看起來這個錯誤是沉默的,所以你可能永遠不會注意到。

my %words = %words_count; 

在這裏,你做的%words_count副本,這似乎是多餘的,因爲你不會再使用它。如果你有一個大的散列,這可能會降低性能。

my $key_count = 0; 
$key_count = keys %words; 

這可以在一行中完成:my $key_count = keys %words。在我看來,更具可讀性。

$value_count = $words{$key} + $value_count; 

也可以簡化爲+=操作:$value_cont += $words{$key}

這是非常好的,你使用嚴格和警告。

+0

您一直非常有幫助。你回答的時候我問的很多,謝謝你指出我的缺點,我用過很多我在網上看過或看過的東西,然後適應我的代碼,我在這個項目中學到了很多東西。 –

+0

不客氣 – TLP

+0

儘管我不確定我的停用詞有什麼不好, –

3

如果性能是不是一個大問題

(sort {$words{$a} <=> $words{$b}} keys %words)[0..4]) 

,如果你確實需要殺手級速度,選擇排序,其經過5次迭代結束可能是你最好的東西。

my @results; 
for (0..4) { 
    my $maxkey; 
    my $max = 0; 

    for my $key (keys %words){ 
    if ($max < $words{$key}){ 
     $maxkey = $key; 
     $max = $words{$key}; 
    } 
    } 
    push @results, $maxkey; 
    delete $words{$maxkey}; 
} 

say join(","=>@results); 
+0

速度現在不是真正的問題,但我會考慮速度的方式,因爲我正在做大規模的速度需要加速。感謝您的幫助。 –

+0

更新了線性時間解決方案 – jozefg

1

這裏有CPAN模塊,Sort::Key::Top。 它有一個直接的接口和高效的XS實現:

use Sort::Key::Top qw(rnkeytop); 

my @results = rnkeytop { $words{$_} } 5 => keys %words;