【问题标题】:Reversing a hash, getting its keys, and sorting反转哈希,获取其键并排序
【发布时间】:2011-08-18 03:04:01
【问题描述】:

我还在学习 Perl,所以可能有更有效的方法来做这件事。我正在尝试获取哈希,将其反转为 $values => $keys,获取新键(旧值),然后对这些键进行排序。

这是有问题的代码:

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

...}

我期望发生的是反向 %hash 将返回一个哈希类型,这就是键正在寻找的。但是,我收到以下错误:

arg 1 到键的类型必须是散列(而不是反向)

我尝试在反向 %hash 周围加上括号,但仍然得到相同的结果。

任何想法为什么这不起作用?

【问题讨论】:

    标签: perl hash


    【解决方案1】:

    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}} 不会返回任何重复值。

    【讨论】:

    • 感谢您的回复。这可能超出了我的水平(我仍在学习 Perl 第 6 版),但是我可以在哪里阅读更多关于使用 %{{}} 的信息。可悲的是,谷歌没有该术语的任何内容。
    • perldoc.perl.org/perlref.html 底部的“另请参阅”部分还有一些链接。
    【解决方案2】:

    keys 的参数必须是哈希、数组或表达式,而不是列表。如果你这样做了

    keys { reverse %hash }
    

    你会得到你期望的结果,因为括号创建了一个匿名哈希。另一方面,Parens 只会改变优先级。或者,在这种情况下,它们可能被认为与函数 keys() 相关,因为大多数 perl 函数都有可选的括号。

    另外,如果你只想要哈希值,你可以使用:

    values %hash
    

    有关详细信息,请参阅 reversevalueskeys 的文档。

    【讨论】:

    • 感谢您的回复。在发布之前,我不完全理解在哈希上使用反向。从 perldoc page for reverse 看起来 reverse 展开原始哈希,然后构建一个新哈希。但是,我仍然认为这个新的哈希将是 reverse 的返回值。我尝试在 reverse 和 %hash 周围添加括号,但仍然遇到同样的问题。
    • 我不知道你是不是说你还有问题。 reverse 返回一个 list,而不是哈希。列表基本上是(1,2,3,4,5,6),如果您尝试将其与keys 一起使用,它将采用第一个值1,尝试使用它,然后丢弃其余的。
    • {reverse %hash} 是对哈希的引用,这也不是keys 的合适参数(我已更正——您可以在 Perl >=v5.14 中使用哈希引用)
    【解决方案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 
    

    【讨论】:

    • 感谢您的回复。虽然这可行,但我更想知道为什么我发布的代码没有按预期运行。再次感谢!
    • @chris,因为您没有将哈希传递给keys,就像错误消息中所说的那样。
    【解决方案4】:

    5.14 之前,keys 返回哈希的键。这需要一个哈希。你没有提供一个。 reverse 不返回哈希值。事实上,不可能返回散列,因为只能返回标量。 (在内部,Perl 可以将哈希直接放在堆栈上,但用户永远不会看到它,而不会导致“奇怪”的错误消息。)在编译时检测到此错误。

    5.14 更灵活。它还将接受对哈希的引用。 (它也将接受数组和对数组的引用,但这与这里无关。)引用是标量,因此它们可以由函数返回。您的代码实际上会使其运行时,但无论您在标量上下文中返回的 reverse 都不会引用不存在的哈希,因此您的代码将在那时死掉。


    你有理由想要反转哈希吗?

    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};
       ...
    } 
    

    【讨论】:

      猜你喜欢
      • 2018-07-21
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多