如何使用map合并哈希数组?

时间:2016-04-08 18:59:37

标签: perl hash merge

希望有人可以为此解释正确的过程。我有这样的数据结构:

echo json_encode( $results, JSON_NUMERIC_CHECK );

WK密钥可能存在也可能不存在。 Author密钥将始终存在,我正在尝试合并这些重复项。覆盖值是可以的(如果已定义)。

我应该尝试[ { Author => "101", WK1 => "", WK10 => "", WK11 => "", WK12 => "", WK13 => "", WK14 => "X", WK15 => "", }, { Author => "102", WK1 => "", WK10 => "", WK11 => "", WK12 => "X", WK13 => "X", WK14 => "", WK15 => "", WK2 => "X", WK3 => "X", WK4 => "", }, { Author => "101", WK1 => "", WK10 => "", WK11 => "", WK12 => "", WK13 => "", WK14 => "X", WK15 => "X", }, ] (不确定如何),还是使用作为键创建新哈希,将其他值推入数组会更好?像

这样的东西
map

抓头

3 个答案:

答案 0 :(得分:1)

听起来好像你开始使用以下内容:

my $records = [
   { Author => "101", WK1 => "", WK2 => "X", WK3 => "X" },
   { Author => "101", WK1 => "X", WK2 => "", WK4 => "X" },
   { Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
];

听起来你想要产生以下内容:

my $records_by_author = (
   "101" => { Author => "101", WK1 => "X", WK2 => "", WK3 => "X", WK4 => "X" },
   "102" => { Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
);

以下将会这样做:

my %records_by_author;
for my $record (@$records) {
   my $author = $record->{Author};
   $records_by_author{$author} = {
      ( $records_by_author{$author} ? %{ $records_by_author{$author} } : () ),
      %$record,
   };
}

如果您想要以下输出:

my $records = [
   { Author => "101", WK1 => "X", WK2 => "", WK3 => "X", WK4 => "X" },
   { Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
];

只需添加以下内容:

$records = [ values(%records_by_author) ];

你想要这个输出,你想保留原始的顺序,请告诉我。

答案 1 :(得分:0)

我建议按照下面的代码进行合并。从@$data中的每个匿名哈希中,获取作者标识符,然后更新合并的WK值,我们永远不会用空的字符串覆盖非空字符串。

您可以对map执行相同操作,这是值得的练习。它似乎更自然地作为嵌套结构循环阅读。

my %authorwk;

for (my $i = 0; @$data; ++$i) {
  local $_ = shift @$data;
  die "$0: missing Author in record $i" unless exists $_->{Author};

  my $author = $_->{Author};
  while (my($wk,$present) = each %$_) {
    next unless $wk =~ /^WK/;
    $authorwk{$author}{$wk} = $present
      if $present || !exists $authorwk{$author}{$wk};
  }
}

答案 2 :(得分:0)

map在这里不合适:一系列切片分配都是必要的

看起来像这样。请注意,唯一重复的作者101在两个实例中都有一组相同的键,因此我已将键WK7添加到第一个实例,将WK8添加到第二个实例,以便您可以看到他们都被添加到结果

use strict;
use warnings 'all';

my $data =  [
  {
    Author => 101,
    WK7    => "7", WK1    => "", WK10   => "",  WK11   => "",
    WK12   => "",  WK13   => "", WK14   => "X", WK15   => "",
  },
  {
    Author => 102,
    WK1    => "",  WK10   => "", WK11   => "",  WK12   => "X",
    WK13   => "X", WK14   => "", WK15   => "",  WK2    => "X",
    WK3    => "X", WK4    => "",
  },
  {
    Author => 101,
    WK8    => "8", WK1    => "", WK10   => "",  WK11   => "",
    WK12   => "",  WK13   => "", WK14   => "X", WK15   => "X",
  },
];


my %authors;

for my $item ( @$data ) {
    my $author = $item->{Author};
    @{ $authors{$author} }{keys %$item} = values %$item;
}

use Data::Dump;
dd \%authors;

输出

{
  101 => {
           Author => 101,
           WK1    => "",
           WK10   => "",
           WK11   => "",
           WK12   => "",
           WK13   => "",
           WK14   => "X",
           WK15   => "X",
           WK7    => 7,
           WK8    => 8,
         },
  102 => {
           Author => 102,
           WK1    => "",
           WK10   => "",
           WK11   => "",
           WK12   => "X",
           WK13   => "X",
           WK14   => "",
           WK15   => "",
           WK2    => "X",
           WK3    => "X",
           WK4    => "",
         },
}