什么是将哈希表反转的最优雅方式?

7

最优雅的方法是将哈希表反转吗?

我的意思是将键和值互换(假设所有的值都是100%唯一的)。

例如:

开始为

my %start = (1=>"a", 2=>"b", 3=>"c");

# ...

# PROFIT: 
my %finish = ("c" => 3, "b" => 2, "a" => 1);

我知道可以用蛮力的方式来做:

foreach my $key (keys %start) {
    my $value = $start{$key};
    $finish{ $value } = $key;
}

但这可能不是最优雅的Perl方式!

你的暴力方法不正确。你需要循环遍历keys %start - cjm
2
“100%独一无二”是什么意思?你从事广告行业吗?某物可以是“95%独一无二”吗?你会告诉你的妻子她是你“95%独一无二的爱情”吗? - Kerrek SB
@cjm - 你说得对。我编辑了一下修复了代码,并通过在最小范围内声明变量为词法作用域来进行了一些清理(换句话说,到处都加了my)。Ike - 如果你不同意,可以随时撤销这些编辑。 - DVK
@KerrekSB - 我是一名软件开发人员。这意味着没有重复项,也就是说您不必担心多个键被映射到同一个值(在这种情况下,您需要删除一些键或将一组键添加为列表)。如果我的英语不完美,我很抱歉。 - Ike
@Ike,我认为Kerrek在指出它们要么是独一无二的,要么不是,没有中间状态。 - tangent
2个回答

15

reverse 可能是最常用的方式之一:

my %finish = reverse %start;

这段代码有效是因为reverse将%start哈希表作为一个(key1 value1 key2 value2... keyN valueN)的列表进行了反转;然后,将该列表分配给哈希变量,使其成为一个哈希表,其中奇数元素变为键,偶数元素变为值。

或者你可以使用map(不太优雅但仍符合惯用法):

my %finish = map { ( $start{$_} => $_ ) } keys %start;

3
@finish{value %start} = keys %start 保留现有的键值对。 - tchrist
1
“reverse %start”很聪明,但可能过于聪明了。 - cjm
1
@tchrist,另外,您在“values”中漏掉了“s”。(请查看我的回答,在您的评论之前仅发布了1秒钟。) - cjm
1
@Ike 我的版本会向现有哈希表中添加内容。它会保留那些键没有被重新分配的键/值对。如果你想要一个全新的哈希表,reverse 版本才适用。 - tchrist
4
@tchrist - 我看过的最直观的解释是,“符号表示您正在检索的数据结构中的数据量($ 表示 1 个元素,@ 表示元素列表,% 表示整个哈希表),而大括号样式表示您的数据结构是什么(方括号表示数组,花括号表示哈希表)。 - DVK
显示剩余12条评论

10
my %start = (1=>"a", 2=>"b", 3=>"c");

my %finish;
@finish{values %start} = keys %start;

上周我花了半个[CENSORED]小时向一群Perl初学者解释一个解决方案。我已经决定将其从教材中删除。他们根本无法理解哈希切片。他们总是困在头脑中认为@表示数组;他们不理解它需要{来表示哈希,而@是无关紧要的。 - tchrist
1
有一个巧妙的解决方案,虚拟+1(暂时不能点赞)。我不是完全的初学者,所以没有像上面评论中的学生们那样遇到同样的问题 :) - Ike
@ike - 你现在应该有足够的声望来投票了。我也给你点赞,因为这是一个很棒的习惯用语。 - DVK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接