将数组转换为哈希表时,反转键和值的顺序

3
假设我有一个值数组,然后是键(与散列的赋值相反):
use strict;
use warnings;
use Data::Dump;

my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);

my %hash = @arr;

dd \%hash;

打印
{ 1 => "uno", 2 => "dos", 3 => "tres", 4 => "cuatro" }

很明显,在构建哈希表时会消除重复的键。

我如何颠倒用于构建哈希表的值对的顺序?

我知道可以编写类似C风格的循环:

for(my $i=1; $i<=$#arr; $i=$i+2){
    $hash{$arr[$i]}=$arr[$i-1];
    }

dd \%hash;   
# { cuatro => 4, dos => 2, four => 4, one => 1, three => 3, tres => 3, two => 2, uno => 1 }

但那看起来有点笨拙。我正在寻找更符合 Perl 语言习惯的方法。

在 Python 中,我只需执行 dict(zip(arr[1::2], arr[0::2])) 即可。

3个回答

8

哦!当然!这甚至让Python看起来更复杂了! - the wolf
使用 perldoc perlfunc 作为参考来查找函数。我在学习 Perl 的时候发现它非常有用。 - TLP
我知道 reverse 这个函数;只是没有联想到它可以用来翻转整个数组,因为在 Python 中,构建关联数组需要使用键值对元组。我一直认为需要逐个反转每个键值对,而现在显然只需要反转整个数组即可。 - the wolf

4

TLP 给出了正确的答案,但避免消除重复键的另一种方法是使用数组哈希。我假设这就是你首先反转数组的原因。

use strict;
use warnings;
use Data::Dump;

my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);

my %hash;

push @{ $hash{$arr[$_]} }, $arr[$_ + 1] for grep { not $_ % 2 } 0 .. $#arr;

dd \%hash;

输出:

{
  1 => ["one", "uno"],
  2 => ["two", "dos"],
  3 => ["three", "tres"],
  4 => ["four", "cuatro"],
}

如评论中ikegami所建议的那样,您可以查看CPAN上可用的List::Pairwise模块以获得更易读的解决方案:

use strict;
use warnings;
use Data::Dump;
use List::Pairwise qw( mapp ); 

my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);

my %hash;

mapp { push @{ $hash{$a} }, $b } @arr;

dd \%hash;

1
你的回答有远见。我也正考虑这样做。谢谢! - the wolf
1
非常好 - 极致紧凑。 :) - clt60
2
+1,我只能猜测为什么@ikegami没有提到核心库List::Util http://perldoc.perl.org/List/Util.html#%24count-%3d-pairmap-%7b-BLOCK-%7d-%40kvlist - mpapec

0

TLP有正确的答案,如果您的值数组和键已准备好进入哈希表。

话虽如此,如果您想在它们进入哈希表之前以任何方式处理键或值,我发现这是我使用的东西:

while (my ($v, $k)=(shift @arr, shift @arr)) {
    last unless defined $k;
    # xform $k or $v in someway, like $k=~s/\s*$//; to strip trailing whitespace...
    $hash{$k}=$v;
}

(注意--对数组@arr是具有破坏性的。如果您想要将@arr用于其他用途,请先制作一份副本。)


1
@ThisSuitIsBlackNot:循环对数组具有破坏性。如果您想保留原始数组值,您需要复制它,不是吗? - dawg
1
这里的优点就像Python中的zip一样,这个循环截断了奇数的键或值。在Perl中,%hash = @arr;的赋值会因为键和值的数量不正确而失败。 - the wolf
@thewolf 实际上这不会导致 Perl 程序崩溃,但它会发出警告 Odd number of elements in hash assignment。不过如果你使用 use warnings FATAL => 'all';,你可以让它崩溃,如果你喜欢更严格的代码。 - TLP

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