【问题标题】:How to get Data::Diver to produce arrays?如何让 Data::Diver 生成数组?
【发布时间】:2014-12-24 10:28:12
【问题描述】:

下面的脚本会输出

$VAR1 = {
          'tank' => {
                      'fs' => {
                                'fs2b' => undef,
                                'fs2a' => undef,
                                'fs2c' => undef
                              }
                    }
        };

我真的想要这样的数组散列散列

$VAR1 = {
          'tank' => {
                      'fs' => [
                                'fs2a',
                                'fs2b',
                                'fs2c'
                              ]
                    }
        };

问题

Data::Diver 将如何实现?

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Data::Diver 'DiveRef';

my @array = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c");
my %hash = ();

foreach my $element (@array) {
    DiveRef( \%hash, \( split /\//, $element ) );
}

print Dumper \%hash;

(代码由ysththis answer 中提供给另一个问题。)

更新

代码中的数组只是一个例子。真正的数组有大约 100 个元素,所以解决方案不能硬编码。

【问题讨论】:

  • 数据结构是否总是HoHoA?

标签: perl


【解决方案1】:
DiveVal(\%data, 'tank', 'fs', 0) = 'fs2a';
DiveVal(\%data, 'tank', 'fs', 1) = 'fs2b';
DiveVal(\%data, 'tank', 'fs', 2) = 'fs2c';

push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2a';
push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2b';
push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2c';

要从"tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c" 获得所需的数据结构,需要额外的信息。以您为例,您可能会理解数据结构始终是 HoHoA。

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c");
my %data;
for (@data) {
   my @parts = split qr{/};
   if (@parts < 3) {
       DiveVal(\%data, map \$_, @parts);
   } else {
       my $val = pop(@parts);
       push @{ DiveVal(\%data, map \$_, @parts) }, $val; 
   }
}

但是这样一个有限的结构,没有理由使用Data::Diver。避免它会快得多。

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c");
my %data;
for (@data) {
   my @parts = split qr{/};
   if    (@parts == 1) { \( $data{$parts[0]}            ); }
   elsif (@parts == 2) { \( $data{$parts[0]}{$parts[1]} ); }
   else { push @{ $data{$parts[0]}{$parts[1]} }, $parts[2]; }
}

你甚至可以使用

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c");
my %data;
for (@data) {
   my @parts = split qr{/};
   push @{ $data{$parts[0]}{$parts[1]} }, $parts[2] if @parts == 3;
}

【讨论】:

  • 最后一个太棒了!倒数第二个给我一个Useless use of push 错误和if 行的语法错误。
  • 修复了各种错误。最后一个假设只有一个或两个部分的项目是多余的(即最终会出现一个包含三个部分的项目)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2021-12-19
  • 1970-01-01
相关资源
最近更新 更多