2015-06-01 109 views
2

我的哈希值包含二進制數作爲鍵:自定義排序方法,它會自動使用approporiate哈希

my %h = ("1010" => 1, "1110" => 0, "0001" => 3, "1100" => 2); 

在Perl中,我可以使用自定義功能進行排序哈希。這是我整理的二進制數,從最低到最大功能:

sub sort_binary_numbers { 
    my $a_dec = oct("0b".$a); 
    my $b_dec = oct("0b".$b); 
    return $a_dec <=> $b_dec; 
} 

我可以使用此功能下列方式排序哈希:

print Dumper sort sort_binary_numbers keys %h; 

而結果將是:

$VAR1 = '0001'; 
$VAR2 = '1010'; 
$VAR3 = '1100'; 
$VAR4 = '1110'; 

我想使用值而不是鍵來排序哈希值。我可以做以下事情:

print Dumper sort { $h{$b} <=> $h{$a} } keys %h; 

正如你所看到的,我必須在排序塊中使用散列名稱。問題是如何重寫這個排序功能塊(如上面的例子)並自動在函數中獲得合適的散列名稱。我嘗試使用@_訪問哈希名稱,但未打印,例如

sub sort_by_value { 
    print Dumper @_; # This was not printed 
    print ref @_; # This was not printed 
    return $b <=> $a; 
} 

,並調用它下面的方式:

print Dumper sort sort_by_value keys %h; 

有趣的是,當我把這個包分揀到另一個功能,從這個函數調用它的循環,我將獲得的數據自卸車的輸出以前缺少的(但我還是沒有得到裁判命令的輸出):

sub calling_from_function { 
    my %h = %{$_[0]}; 
    foreach my $key (sort sort_by_value keys %h){ 
    } 
} 

&calling_from_function(\%h); 

然後我得到這樣的輸出:

$VAR1 = { 
      '0001' => 3, 
      '1010' => 1, 
      '1110' => 0, 
      '1100' => 2 
     }; 
$VAR1 = { 
      '0001' => 3, 
      '1010' => 1, 
      '1110' => 0, 
      '1100' => 2 
     }; 
$VAR1 = { 
      '0001' => 3, 
      '1010' => 1, 
      '1110' => 0, 
      '1100' => 2 
     }; 
$VAR1 = { 
      '0001' => 3, 
      '1010' => 1, 
      '1110' => 0, 
      '1100' => 2 
     }; 

問題:

  1. 我如何替換此命令print Dumper sort { $h{$b} <=> $h{$a} } keys %h;與功能排序塊,並得到sortign函數中的散列的適當的名稱?
  2. 爲什麼從其他函數包裝起作用?
  3. 爲什麼ref不起作用?
+1

參見[我可以傳遞參數排序在Perl比較子例程?(http://stackoverflow.com/q/3995537/176646) – ThisSuitIsBlackNot

+2

還請注意,如果您只是想對'Data :: Dumper'輸出進行排序,則可以使用'$ Data :: Dumper :: Sortkeys':「也可以設置爲子程序引用,該引用將針對每個散列進行調用在這種情況下,'Data :: Dumper'將爲每個散列調用一次子程序,並將散列引用傳遞給子程序。子程序的目的是返回一個將被轉儲的鍵的數組的引用,那個命令應該傾倒。「 – ThisSuitIsBlackNot

+2

順便說一句,'sort sort_binary_numbers keys%h;'可以縮短爲'sort keys%h;'' – ikegami

回答

4

排序子程序不帶參數正常(即除非原型都參與)通過@_,而是通過$a$bref @array永遠不會返回任何東西,因爲數組永遠不會是一個引用。

由另一個函數包裝,因爲您通過參數向包裝器填充@_

使用的包裝排序任何哈希:

sub sort_by_value { 
    my %h = @_; 
    return sort { $h{$b} <=> $h{$a} } keys %h 
} 

print Dumper(sort_by_value(%h)); 

您還可以發送哈希參考子程序:

sub sort_by_value { 
    my ($h) = @_; 
    return sort { $h->{$b} <=> $h->{$a} } keys %$h 
} 

print Dumper sort_by_value(\%h); 
3

所以,你想有一個通用的排序功能,如

my $sorter = sub { $_[0]{$b} <=> $_[0]{$a} }; 

當需要分類時,只需使用

my @sorted_keys = sort { $sorter->(\%h) } keys(%h); 
3

您可以使用散列作爲列表,將其轉換爲k/v aref對,對值進行排序(第二個元素),然後從排序列表中選擇鍵(大致是僞裝的Schwartzian變換)。

use strict; 
use warnings; 
use List::Util 'pairs'; 

my %h = ("1010" => 1, "1110" => 0, "0001" => 3, "1100" => 2); 
my @k = map $_->[0], 
    sort { $b->[1] <=> $a->[1] } 
    pairs %h; 

無需額外的模塊,

my @k = map $_->[0], 
    sort { $b->[1] <=> $a->[1] } 
    map [ $_, $h{$_} ], 
    keys %h;