【问题标题】:Perl sort by hash value in array of hashes or hash of hashesPerl按散列数组或散列散列中的散列值排序
【发布时间】:2014-05-19 23:17:35
【问题描述】:

谁能告诉我我在这里做错了什么?我已经尝试了几乎所有我能想到的数组/哈希类型和排序查询的组合,但似乎无法让它发挥作用。

我正在尝试按value1 对下面的哈希引用进行排序:

my $test = {
    '1' => { 'value1' => '0.001000', 'value2' => 'red'},
    '2' => { 'value1' => '0.005000', 'value2' => 'blue'},
    '3' => { 'value1' => '0.002000', 'value2' => 'green'},
    '7' => { 'value1' => '0.002243', 'value2' => 'violet'},
    '9' => { 'value1' => '0.001005', 'value2' => 'yellow'},
    '20' => { 'value1' => '0.0010200', 'value2' => 'purple'}
};

使用这个排序循环:

foreach (sort { $test{$a}->{'value1'} <=> $test{$b}->{'value1'} } keys \%{$test} ){
    print "key: $_ value: $test->{$_}->{'value1'}\n"
}

我明白了:

key: 1 value: 0.001000
key: 3 value: 0.002000
key: 7 value: 0.002243
key: 9 value: 0.001005
key: 2 value: 0.005000
key: 20 value: 0.0010200

我尝试过使用整数,但似乎发生了同样的事情。

我实际上不需要循环遍历哈希,我只是希望它被订购以供以后使用。使用哈希数组很容易,但使用哈希哈希就不那么容易了..?

【问题讨论】:

  • 回复。 “我实际上不需要遍历哈希,我只是希望它被订购以供以后使用。”您无法对哈希进行排序。您可以按特定顺序遍历键,但哈希本身不会被排序。
  • 谢谢!这就是我最终要寻找的答案。然后回到数组​​......我认为对数组进行一次排序比在每次需要使用它时对哈希进行排序更快,在我目前的情况下是每秒很多(我想你可以在迭代时创建一个新的哈希键)。
  • 同样,您不能对哈希进行排序。您可以将排序后的键列表存储在一个数组中,并使用它来设置您用于遍历散列的顺序,但这仅在您不从散列中添加或删除元素时才有效。 my @sorted = sort keys %hash; for (@sorted) { ... }

标签: arrays perl sorting hash hash-of-hashes


【解决方案1】:

不要在引用上调用键。在实际哈希上调用它。

另外,这个$test{$a}-&gt; 应该是$test-&gt;{$a},因为$test 是一个哈希引用。

foreach (sort { $test->{$a}{'value1'} <=> $test->{$b}{'value1'} } keys %{$test} ){
    print "key: $_ value: $test->{$_}->{'value1'}\n"
}

如果您打开了 use strict;use warnings;,您会收到以下错误提示您注意某个问题:

Global symbol "%test" requires explicit package name

【讨论】:

  • 谢谢。我可以发誓我试过了,但我想我是用我的 %test = (...);
  • 并且启用的警告会说正在比较的值是未定义的
【解决方案2】:

只是想提供其他答案的来源和工作代码示例。就像他们说的那样,您正在调用 keys 并带有参数的哈希引用。根据documentation


从 Perl 5.14 开始,键可以采用标量 EXPR,它必须 包含对 unblessed 哈希或数组的引用。论据将 被自动取消引用。考虑到键的这一方面 高度实验性。确切的行为可能会在未来发生变化 Perl 版本。

for (keys $hashref) { ... }
for (keys $obj->get_arrayref) { ... }

但是这对我有用:

#!/usr/bin/perl
use strict;
use warnings;

my $test = {
    '1' => { 'value1' => '0.001000', 'value2' => 'red'},
    '2' => { 'value1' => '0.005000', 'value2' => 'blue'},
    '3' => { 'value1' => '0.002000', 'value2' => 'green'},
    '7' => { 'value1' => '0.002243', 'value2' => 'violet'},
    '9' => { 'value1' => '0.001005', 'value2' => 'yellow'},
    '20' => { 'value1' => '0.0010200', 'value2' => 'purple'}
};


foreach (sort { $test->{$a}->{'value1'} <=> $test->{$b}->{'value1'} } keys \%{$test} ) {
    print "key: $_ value: $test->{$_}->{'value1'}\n"
}

例子:

matt@mattpc:~/Documents/test/10$ perl test.pl 
key: 1 value: 0.001000
key: 9 value: 0.001005
key: 20 value: 0.0010200
key: 3 value: 0.002000
key: 7 value: 0.002243
key: 2 value: 0.005000
matt@mattpc:~/Documents/test/10$ perl --version
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
(with 88 registered patches, see perl -V for more detail)

这是使用哈希引用作为keys 的输入,我不推荐这样做。

我建议遵循其他问题的建议并添加 use strictuse warnings 并将哈希引用更改为哈希 %{test}

【讨论】:

    【解决方案3】:

    就是keys %$testkeys 的参数必须是散列,而不是散列引用。 \%${test}$test 相同,是一个参考。

    并使用$test-&gt;{$a},而不是$test{$a},因为$test 是hash-ref,而不是hash。

    foreach (sort { $test->{$a}->{'value1'} <=> $test->{$b}->'{value1'} } keys %$test) {
        print "key: $_ value: $test->{$_}->{'value1'}\n"
    }
    

    或带有一些语法糖的更短形式:您可以省略第一个箭头之后的附加箭头。并且在寻址哈希时不必引用字符串文字键。

    foreach (sort { $test->{$a}{value1} <=> $test->{$b}{value1} } keys %$test) {
        print "key: $_ value: $test->{$_}{value1}\n"
    }
    

    打开use warnings; 通常会有很大帮助,至少对于调试来说是这样。

    【讨论】:

      【解决方案4】:

      我能发现的唯一错误是使用了 hash ref \%{$test},你应该使用 hash %$testkeys 使用它。

      【讨论】:

        猜你喜欢
        • 2014-01-08
        • 2012-08-03
        • 2014-05-07
        • 1970-01-01
        • 1970-01-01
        • 2011-03-13
        • 2018-12-07
        • 2010-11-02
        • 1970-01-01
        相关资源
        最近更新 更多