【问题标题】:Reverse the order of key, value in an array conversion to a hash将数组中键、值的顺序反转为哈希
【发布时间】:2023-03-29 16:23:01
【问题描述】:

假设我有一个值数组,然后是键(与分配给哈希的期望相反):

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]))

【问题讨论】:

    标签: arrays perl hash


    【解决方案1】:

    使用reverse:

    my %hash = reverse @arr;
    

    Perl 中的内置函数列表位于perldoc perlfunc

    【讨论】:

    • 噢!当然!这甚至让 Python 看起来更复杂!
    • 使用perldoc perlfunc 作为查找函数的参考。我在学习 Perl 时发现它非常有用。
    • 我知道reverse;我只是没有连接它可以反转整个数组,因为在 Python 中,关联数组的构造需要在键值对的元组中。我一直认为我需要反转每一对而不是(现在,显然)只是反转整个数组
    【解决方案2】:

    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"],
    }
    

    根据 cmets 中 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,我只能推测为什么@ikegami 没有提到corelib List::Util perldoc.perl.org/List/…
    【解决方案3】:

    TLP 有 right answer 如果您的值数组,键已准备好进入散列。

    也就是说,如果您想在键或值进入散列之前以任何方式处理它们,我发现这是我使用的东西:

    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用于其他用途,请先复制它。)

    【讨论】:

    • @ThisSuitIsBlackNot:循环对数组有破坏性。如果你想保留你原来的数组值,你需要复制它,不是吗?
    • 这里的优点是,就像 Python 中的 zip 一样,这个循环会截断奇数的输出键或值。在 Perl 中,%hash = @arr; 的赋值会因为键、值的数量不正确而死。
    • @thewolf 实际上不会导致 Perl 程序死机,但会发出警告 Odd number of elements in hash assignment。虽然如果你使用use warnings FATAL =&gt; 'all';,你可以让它死掉,如果你喜欢更严格的代码。
    猜你喜欢
    • 2014-07-23
    • 1970-01-01
    • 2016-02-05
    • 2010-10-18
    • 2015-04-19
    • 2012-10-29
    • 2019-10-27
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多