2015-06-01 67 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;