【问题标题】:How do you map an array [key1,val1] to a hash { key1 => val1} in perl?如何在 perl 中将数组 [key1,val1] 映射到哈希 { key1 => val1}?
【发布时间】:2011-11-30 23:40:52
【问题描述】:

问题是我有一个数组,其中键值对作为数组中的元素,我必须以某种方式将它们拆分为散列中的键 => 值对。

我第一次尝试这个工作,但我认为它非常混乱 - 我必须获取数组的所有其他元素,然后过滤以找到接受的键以创建散列

my $HASH;
my $ARRAY = [ key1, val1, key2, val2, __key3__, val3, __key4__, val4 ];
   my @keys = map{ $ARRAY[ $_*2   ] } 0 .. int($#ARRAY/2);
   my @vals = map{ $ARRAY[ $_*2+1 ] } 0 .. int($#ARRAY/2);

   my $i = 0;
   #filter for keys that only have __key__ format
    for $key (@keys){
      if( $key && $key =~ m/^__(.*)__$/i ){
       $HASH{$1} = $vals[$i];
      }
     $i++;
    }
   # only key3 and key4 should be in $HASH now

我发现了这个sample code,我认为它与我正在寻找的很接近,但我不知道如何在数组上实现类似的东西,而不是在文本文件的行上迭代:

$file = 'myfile.txt'
open I, '<', $file
my %hash;
%hash = map { split /\s*,\s*,/,$_,2 } grep (!/^$/,<I>);
print STDERR "[ITEM] $_ => $hash{$_}\n" for keys %hash;

你们中的任何一位 perl 专家都可以帮助我了解最好的方法吗?即使我可以以某种方式将所有元素连接成一个字符串,然后每隔一个空格标记分割一次——这也可能有效,但现在我卡住了!

【问题讨论】:

  • $ARRAY = [...]$ARRAY[...] 指的是两个不同的变量!
  • @nodebunny => 将use warnings; use strict; 添加到您所有程序的顶部,以捕获类似上述mob 注释的问题。
  • 感谢我使用 Moose,所以它已经在上面了!

标签: arrays perl hash map key-value


【解决方案1】:

这很容易:

use strict; use warnings;
use YAML;

my $ARRAY = [qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4)];
my $HASH =  { @$ARRAY };

print Dump $HASH;

输出:

C:\Temp>
---
__key3__: val3
__key4__: val4
键1:val1
key2: val2

【讨论】:

  • 哦,哇,不知道你可以转储数组,散列会弄明白。太棒了!
  • @nodebunny:实际上,我回答的时间戳是提前 35 秒。
  • 请把barewords列表转成qw list,barewords是魔鬼的玩物。
【解决方案2】:
my $ARRAY = [ qw(key1 val1 key2 val2 key3 val3 key4 val4) ];
my $HASH = { @$ARRAY };

【讨论】:

    【解决方案3】:

    在您找到的示例代码中,&lt;I&gt; 部分读入整个文件并将一个列表返回给 grep。 grep 处理列表,然后将其传递给映射。然后 Map 创建自己的列表,并将此列表分配给哈希。

    当您将列表分配给哈希时,该列表被假定为键/值对的偶数列表。

    这个列表来自哪里并不重要,它可以是 map、grep 或 split 命令的输出。它可以直接来自文件,也可以存储在数组中。

    您的线路:

    my $HASH = ();
    

    不做任何有用的事情。写my $HASH; 完全一样。

    此时,$HASH 未定义。当您有一个未定义的值并将其作为哈希 %$HASH 取消引用时,未定义的值将变为哈希。

    您可以通过以下方式明确说明:

    my $HASH = {};  # note the curly braces and not parens
    

    如果你有一个数组中的键值对列表:

    %$HASH = @array;
    

    如果你有一个键列表和一个值列表:

    @$HASH{@keys} = @values;
    

    根据您的问题,这是一种在过滤值的同时从数组创建哈希的简单方法:

    my $HASH = {};
    my $ARRAY = [ qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4) ];
    
    {my @list = @$ARRAY;  # make a copy since splice eats the list
        while (my ($k, $v) = splice @list, 0, 2) {
            if ($k =~ /^__(.+)__$/) {
                $$HASH{$1} = $v
            }
        }
    }
    
    use Data::Dumper;
    
    print Dumper($HASH);
    

    哪个打印:

    $VAR1 = {
              'key4' => 'val4',
              'key3' => 'val3'
            };
    

    如果您想在一行中完成所有操作,您可以使用我的模块List::Gen 中的函数mapn,该函数类似于map,但它允许您以任何步长移动列表想要,而不是一次只有一件。

    use List::Gen 'mapn';
    
    %$HASH = mapn {/^__(.+)__$/ ? ($1, $_[1]) : ()} 2 => @$ARRAY;
    

    【讨论】:

    • 谢谢。问题是我有一个键和值列表——都在同一个数组中,并想从它们创建一个哈希——
    • @nodebunny => 让我知道我刚刚所做的更新是否涵盖了您正在寻找的内容。
    • 我试图弄清楚如何获取我必须使用数组而不是文件行的示例代码——它似乎几乎正确
    • @nodebunny => 见最后一个例子mapn。任何使用 map 和 grep 的解决方案都会变得笨拙,因为这些构造是一次在列表上移动一个元素。它们可以通过使用外部指标或其他技巧来扭曲,但此时您应该使用不同类型的循环。
    【解决方案4】:
    我不知道你可以转储数组,然后散列会弄清楚。

    来自数组的值没有什么神奇之处。哈希没有什么可弄清楚的。

    如果将列表分配给哈希,它将清除哈希,然后将列表视为键值对列表,从中初始化哈希。所以

    %hash = ( foo => 1, bar => 2 );
    

    等价于

    my @anon = ( foo => 1, bar => 2 );
    %hash = ();
    while (@anon) {
       my $key = shift(@anon);
       my $val = shift(@anon);
       $hash{$key} = $val;
    }
    

    列表就是列表。是否使用列表/逗号操作生成无关紧要

    x => "foo", y => "bar"
    

    使用qw()

    qw( x foo y bar )
    

    或使用数组

    @array
    

    这意味着以下都是一样的。

    %hash = ( x => "foo", y => "bar" );
    %hash = qw( x foo y bar );
    %hash = @array;  # Assuming @array contains the correct values.
    

    还有

    $hash = { x => "foo", y => "bar" };
    $hash = {qw( x foo y bar )};
    $hash = { @array };  # Assuming @array contains the correct values.
    

    【讨论】:

    • 好的,关于 => 的部分与 相同,还有什么没有让它特别清楚!谢谢@ikegami
    • @nodebunny,差不多。 =&gt;, 的精美版本,它自动引用它之前的裸词(如果有的话)。
    【解决方案5】:

    由于您的具体情况已经得到解答,我想我会回答我提出您的问题的情况。我希望看到像 [ key =&gt; $value ] 这样的 pairs 数组,并且您想将其放入哈希数组或哈希数组中:

    答案是这样的:

    my %hash = map { @$_ } [[ key1 => $value1 ], [ key2 => $value2 ], ... ];
    my @ha   = map {; { @$_ } } [[ key1 => $value1 ], [ key2 => $value2 ], ... ];
    
    my %hash = @$array_ref_of_values;
    

    只是,我通过解除引用 (@$_) 将每一个都“分解”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-02
      • 2011-10-04
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-11
      • 2015-12-04
      相关资源
      最近更新 更多