【问题标题】:Putting elements of arrays into array of hashes in Perl在 Perl 中将数组元素放入哈希数组中
【发布时间】:2012-10-25 14:20:05
【问题描述】:

为了我自己的教育,有什么巧妙的方法可以转换一些数组,使每个数组都与哈希的键相关联,并且所有这些哈希最终都在一个数组中?

为了让事情更清楚一点,假设我有一些这样的数组:

my @n = ( 1,    2,    3 );
my @f = ( 3.14, 1.21, 0.75 );
my @s = ( 'a',  'b',  'c' );

我想要一个看起来像这样的哈希数组:

my %h = ( number => 1, float => 3.14, string => 'a' );

简单的 C 风格迭代是一个明显的解决方案:

for ( my $i = 0; $i < @n; $i++ ) {
    my %h = ();
    $h{number} = $n[$i];
    $h{float}  = $f[$i];
    $h{string} = $s[$i];
    push @a, \%h;
}

略带 Perlish:

for (0..$#n) {
    push @c, { number => $n[$_], float => $f[$_], string => $s[$_] };
}

或者如果我想简洁而不关心破坏数组:

for (0..$#n) {
    push @a, { number => shift @n, float => shift @f, string => shift @s };
}

还有List::MoreUtils:

use List::MoreUtils qw (each_array);
my $it = each_array @n, @f, @s;
while ( my ($n, $f, $s) = $it->() ) {
    push @a, { number => $n, float => $f, string => $s };
}

那么本着 TMTOWTDI 的精神,我还缺少哪些其他解决方案?

【问题讨论】:

    标签: arrays perl hash


    【解决方案1】:

    不可读,使用切片:

    @{ $d[$_] }{qw/number float string/} = ($n[$_], $f[$_], $s[$_]) for 0 .. $#n;
    

    【讨论】:

      【解决方案2】:

      my @array = map { number =&gt; $n[$_], float =&gt; $f[$_], string =&gt; $s[$_] }, 0 .. $#n;

      我不是 Perl 人,只是一个建议:)

      【讨论】:

        【解决方案3】:

        这个程序可以满足您的要求

        use strict;
        use warnings;
        
        my @n = ( 1,    2,    3 );
        my @f = ( 3.14, 1.21, 0.75 );
        my @s = ( 'a',  'b',  'c' );
        
        my @data;
        for my $i (0 .. $#n) {
          @{$data[$i]}{ qw/ number float string / } = map $_->[$i], \(@n, @f, @s);
        }
        
        use Data::Dump;
        dd \@data;
        

        输出

        [
          { float => 3.14, number => 1, string => "a" },
          { float => 1.21, number => 2, string => "b" },
          { float => 0.75, number => 3, string => "c" },
        ]
        

        或者您可能更喜欢使用List::MoreUtils 库的each_array 函数的解决方案。该程序的输出与我上面之前的解决方案的输出相同。

        use strict;
        use warnings;
        
        use List::MoreUtils 'each_array';
        
        my @n = ( 1,    2,    3 );
        my @f = ( 3.14, 1.21, 0.75 );
        my @s = ( 'a',  'b',  'c' );
        
        my $iter = each_array(@n, @f, @s);
        my @data;
        while ( my @values = $iter->() ) {
          my $i = $iter->('index');
          @{ $data[$i] }{ qw/ number float string / } = @values;
        }
        
        use Data::Dump;
        dd \@data;
        

        【讨论】:

          【解决方案4】:

          这使用了来自List::MoreUtils的一些实用程序

          • mesh 集成数组列表
          • part 对数组进行分区

          还有_POSINT 来自Params::Util 来判断是否 下一个参数是一个正整数。

          use List::MoreUtils qw<mesh part>; # integrate and partition arrays
          use Params::Util    qw<_POSINT>;   # test number positive
          
          # accept size number if positive int, otherwise we will be returning pairs. 
          sub by (@) { 
             my $num = &_POSINT ? shift : 2;
             my $i   = -1;
             return part { int( ++$i / $num ) } @_;
          }
          
          my @n      = qw< 1    2    3 >;
          my @f      = qw< 3.14 1.21 0.75 >;
          my @s      = qw< a    b    c >;
          my @fields = qw<number float string>;
          
          my @results = map { +{ mesh @fields, @$_ } } by 3 => mesh @n, @f, @s;
          

          当然,使用这个,你可以像这样列出数据:

          my @results 
              = map { +{ mesh @fields, @$_ } } 
                by 3 => qw< 1 3.14 a
                            2 1.21 b
                            3 0.75 c
                          >
              ;
          

          跳过第一个mesh。布局表示数据的结构(就像代码一样。)

          【讨论】:

            猜你喜欢
            • 2021-08-01
            • 1970-01-01
            • 2016-05-19
            • 2013-11-01
            • 1970-01-01
            • 2012-10-11
            • 2019-07-30
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多