【问题标题】:Create a hash in which the key is an array, and the value is an array of arrays创建一个哈希,其中键是一个数组,值是一个数组数组
【发布时间】:2013-05-17 12:52:38
【问题描述】:

我正在尝试创建一个哈希,其中键包含在数组中,值包含在数组的数组中:

my @keys = (1,2,3,4,5);
my @value1 = (a,b,c,d,e);
my @value2 = (f,g,h,i,j);
my @value3 = (k,l,m,n,o);

my @values = ([@value1],[@value2],[@value3]);

my %hash;

我想创建一个以@keys 作为键,@values 作为值的散列,以便键'1' 将返回值 a、f、k(每个数组中的第 0 个元素)等等。

对于单个键,这将实现如下:

%hash=('key'=>@values);

但我不确定如何为一组键修改它。

任何帮助都会很棒!

干杯,

没有

【问题讨论】:

  • %hash=('key'=>@values); 是错误的。值必须是标量。您可以使用%hash = ( key => \@values );%hash = ( key => [ @values ] );
  • 每个数组的第 0 个元素的值是 a,f,k 而不是 a,g,k

标签: arrays perl hash multidimensional-array


【解决方案1】:

类似这样的:

my %hash = map { $keys[$_] => [ $value1[$_], $value2[$_], $value3[$_] ] } 0..$#keys;

假设所有四个列表的长度相同。

【讨论】:

  • 注意'keys'以'1'而不是'0'开头?
  • 所以?我确实使用了@keys 而不是0..$#keys
  • Perl 数组中的第一个索引号是多少?因此,第一个地图循环 $_ 将是“1”而不是“0”。您可以从他的代码示例中跳过“a”、“f”和“k”。也许是 $value1[$_-1]?
  • 这很好用,但是对于每个键,它为每个值返回 [0]。例如:key: 1, Values: a f kkey: 2, Values: a f kkey: 3, Values: a f k有没有办法打印key1的values[0],key2的values[1]...?
【解决方案2】:

我利用语法$foo[$i][$j]; 将您的数组表示为二维数组。这是一个没有map的答案:

#! /usr/bin/env perl

use 5.12.0;
use warnings;
use Data::Dumper;

my @keys = qw(alpha beta gamma delta epsolon);

my @values1 = qw(one two three four five);
my @values2 = qw(uno dos tres quatro cinco);
my @values3 = qw(a b c d e);

my @values = ( \@values1, \@values2, \@values3 );

my %hash;
for my $item ( (0..$#keys) ) {
    my @array;
    push @array, $values[0][$item], $values[1][$item], $values[2][$item];
    $hash{$keys[$item]} = \@array;
}

say Dumper \%hash;

这是输出:

$VAR1 = {
      'gamma' => [
           'three',
           'tres',
           'c'
         ],
      'delta' => [
           'four',
           'quatro',
           'd'
         ],
      'alpha' => [
           'one',
           'uno',
           'a'
         ],
      'beta' => [
          'two',
          'dos',
          'b'
        ],
      'epsolon' => [
             'five',
             'cinco',
             'e'
           ]
    };

看起来不错。当然,我从来没有验证过各种数组的大小都是一样的。

【讨论】:

  • my @array = map $values[$_][$item], 0..2; 稍微缩短一点。
  • 我不是map 的粉丝。我没有发现它比循环更有效,而且我发现它更难维护。我更喜欢可读性。这就是我创建@array 以在push 中使用而不是仅仅使用@{ $hash{$keys[$item]} }; 的原因。后者让我的大脑受伤。值得使用@array,即使它需要两行额外的代码,只是因为它可以更容易地查看正在发生的事情。几乎每次看到map,我都不得不停下来想想它在做什么。
【解决方案3】:

试试这个...

#! /usr/bin/perl 使用严格; 使用警告; 使用 Data::Dumper; 我的@keys = qw(undef 0 1 $key kappa); 我的@value1 = qw(a b c d e); 我的@value2 = qw(f g h i j); 我的@value3 = qw(k l m n o); #这里没有用到... # 我的@values = ([@value1],[@value2],[@value3]); 我的 %hash = map { 我的 $key = "$keys[$_]"; $key => [ $value1[$_], $value2[$_], $value3[$_] ] } (0..$#keys); 对于我的 $key ( 排序键 %hash ) { print "密钥:$key 包含:"; 对于我的 $value (@{$hash{$key}}) { 打印“$值”; } 打印“\n”; } print "应该打印 'c':".@{$hash{'1'}}[0]."\n"; print "应该打印'j':".@{$hash{'kappa'}}[1]."\n"; # print Dumper( %hash );

预期输出如下:

密钥:$key 包含:d i n 键:0 包含:b g l 键:1 包含:ch m 键:kappa 包含:e j o 键:undef 包含:a f k 应该打印'c':c 应该打印'j':j

添加:如果您想访问散列中的单个值,它应该被 @{} 包围以转换匿名数组引用,然后以方括号中的索引(从零开始)结束,例如[0]。例子:

print "应该打印 'c':".@{$hash{'1'}}[0]."\n"; print "应该打印'j':".@{$hash{'kappa'}}[1]."\n";

修改为包含 Ekkehard 对 (0..$#..) 的更正确用法,并添加了一些键的防弹功能。

【讨论】:

    【解决方案4】:

    结合 Vedran 和 Jim 的最佳解决方案:

    use strict;
    use warnings;
    
    # my @keys   = ( 1,  2,  3,  4,  5);
    my @keys   = ( 'alpha','beta','gamma','delta','epsilon');
    my @value1 = ('a','b','c','d','e');
    my @value2 = ('f','g','h','i','j');
    my @value3 = ('k','l','m','n','o');
    
    my %hash = map { $keys[$_] => [ $value1[$_], $value2[$_], $value3[$_] ] } (0 .. $#keys);
    printf 'first (%s) value: [%s]', $keys[0], join ", ", @{$hash{$keys[0]}};
    

    输出:

    first (alpha) value: [a, f, k]
    

    或:

    first (1) value: [a, f, k]
    

    取决于您选择的@keys。

    【讨论】:

      【解决方案5】:
      use Algorithm::Loops 'MapCarE';
      my @keys = qw(1 2 3 4 5);
      my @value1 = qw(a b c d e);
      my @value2 = qw(f g h i j);
      my @value3 = qw(k l m n o);
      
      my %hash = MapCarE { $_[0] => [ @_[1..$#_] ] } \(@keys, @value1, @value2, @value3);
      

      MapCarE 循环遍历数组,调用您提供的代码,首先传递数组的第一个元素,然后是第二个元素,等等。

      【讨论】:

        猜你喜欢
        • 2015-02-02
        • 1970-01-01
        • 1970-01-01
        • 2019-05-01
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        • 2021-06-24
        • 1970-01-01
        相关资源
        最近更新 更多