反转哈希,获取其密钥和排序

时间:2011-08-18 03:04:02

标签: perl hash

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

以下是相关代码:

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

...}

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

arg 1到键的类型必须是哈希(不是反向)

我已经尝试将括号括在反向%hash中,但仍然可以得到相同的东西。

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

4 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

keys的参数必须是散列,数组或表达式,而不是列表。如果你做了

keys { reverse %hash }

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

此外,如果您只想要哈希值,可以使用:

values %hash

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

答案 2 :(得分: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 

答案 3 :(得分:3)

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