2

我有两个具有以下内容的 perl 哈希:

第一的:

$VAR1 = {
      'name1' => [
                   'adam',
                   'bob'
                 ],
      'name2' => [
                  'Miller',
                  'Schumacher'
                ]
    };

第二:

$VAR1 = {
      'name1' => [
                   'tina',
                   'jason',
                   'jeff'
                 ],
      'name2' => [
                  'Miller',
                  'Schumacher',
                  'Schmidt'
                ]
    };

如何合并它们以获得以下结构并获得 name2 中的唯一项目?

$VAR1 = {
      'name1' => [
                   'tina',
                   'jason',
                   'jeff',
                   'adam',
                   'bob',
                 ],
      'name2' => [
                  'Miller',
                  'Schumacher',
                  'Schmidt'
                ]
    };
4

4 回答 4

2

Hash::Merge模块的正确先例行为被定制为在合并数组时统一元素。

use strict;
use Hash::Merge qw/merge :custom/;
use List::MoreUtils qw/uniq/;
use Data::Dumper;

my $href1 = { name1 => [ qw/adam bob/ ],
              name2 => [ qw/Miller Schumacher/ ] };

my $href2 = { name1 => [ qw/tina jason jeff/ ],
              name2 => [ qw/Miller Schumacher Schmidt/ ] };

Hash::Merge::specify_behavior(  {
                        SCALAR => {
                                SCALAR => sub { $_[1] },
                                ARRAY  => sub { [ $_[0], @{$_[1]} ] },
                                HASH   => sub { $_[1] },
                        },
                        ARRAY => {
                                SCALAR => sub { $_[1] },
                                # This returns unique elements from two arrays passed
                                ARRAY  => sub { [ uniq( @{$_[0]}, @{$_[1]}) ] },
                                HASH   => sub { $_[1] }, 
                        },
                        HASH => {
                                SCALAR => sub { $_[1] },
                                ARRAY  => sub { [ values %{$_[0]}, @{$_[1]} ] },
                                HASH   => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) }, 
                        },
                }, 
                'Right precedent + Uniq array', 
        );

my $href3 = merge($href1, $href2);

print Dumper $href3;

产生输出:

$VAR1 = {
          'name2' => [
                       'Miller',
                       'Schumacher',
                       'Schmidt'
                     ],
          'name1' => [
                       'adam',
                       'bob',
                       'tina',
                       'jason',
                       'jeff'
                     ]
        };
于 2015-10-03T12:40:56.940 回答
1

您必须遍历键并从数组中name1, name2过滤出重复项 ,$VAR2->{$k}$VAR1->{$k}

use strict;
use warnings;

my $VAR1 = {
      'name1' => [ 'adam', 'bob' ],
      'name2' => [ 'Miller', 'Schumacher' ]
};
my $VAR2 = {
      'name1' => [ 'tina', 'jason', 'jeff' ],
      'name2' => [ 'Miller', 'Schumacher', 'Schmidt' ]
};

my %result;
for my $k (keys %$VAR1) {
  my %seen;
  $result{$k} = [
    grep { !$seen{$_}++ } @{ $VAR2->{$k} }, @{ $VAR1->{$k} }
  ];
}

use Data::Dumper;
print Dumper \%result;

输出

$VAR1 = {
      'name2' => [
                   'Miller',
                   'Schumacher',
                   'Schmidt'
                 ],
      'name1' => [
                   'tina',
                   'jason',
                   'jeff',
                   'adam',
                   'bob'
                 ]
    };
于 2015-10-03T10:01:29.873 回答
1

这是一个通用的解决方案,可以采用任意数量的散列,并处理任何散列中缺少的键

它遍历要组合的所有哈希键的列表,并使用所有哈希连接每个键的数组值map

Data::Dump只用来显示生成的哈希数据

use strict;
use warnings;

use List::MoreUtils qw/ uniq /;
use Data::Dump;

my %ha = (
    name1 => [ "adam",   "bob" ],
    name2 => [ "Miller", "Schumacher" ],
);

my %hb = (
    name1 => [ "tina",   "jason",      "jeff" ],
    name2 => [ "Miller", "Schumacher", "Schmidt" ],
);

my @hashes = \( %ha, %hb );

my %new;

for my $k ( uniq map keys %$_, @hashes ) {
    $new{$k} = [
        uniq map @{ $_->{$k} // [] }, @hashes
    ];
}

dd \%new;

输出

{
  name1 => ["adam", "bob", "tina", "jason", "jeff"],
  name2 => ["Miller", "Schumacher", "Schmidt"],
}

如果出于任何原因您不想安装非核心库模块List::MoreUtils,那么您可以使用此版本的uniq函数

sub uniq {
  my %seen;
  grep { not $seen{$_}++ } @_;
}
于 2015-10-03T12:08:21.460 回答
1

如果您的需求非常具体 - 将两个哈希与键name1和合并name2,那么以下应该可以解决问题:

my $first = {
        name1 => [ qw(adam bob) ],
        name2 => [ qw(Miller Schumacher) ],
    };
my $second = {
        name1 => [ qw(tina jason jeff) ],
        name2 => [ qw(Miller Schumacher Schmidt) ],
    };

my $merged = {
        name1 => [ values %{$first->{name1}}, values %{$second->{name1}} ],
        name2 => [ values %{$first->{name2}}, values %{$second->{name2}} ],
    };

如果密钥不是固定的并且事先不知道,Сухой27 的答案将起作用,至少在结构只有两层深的情况下。如果它可以更深入,您将需要一个递归解决方案。

于 2015-10-03T11:12:30.027 回答