合并Perl Hashrefs并且独一无二

时间:2015-10-03 09:53:58

标签: arrays perl merge unique hashref

我已经得到了两个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 个答案:

答案 0 :(得分: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'
                     ]
        };

答案 1 :(得分:1)

您必须循环 if(!isset($_GET['enable']) && !isset($argv[1]) == "enable") { echo 'Invalid request'; return; } 个密钥并从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;

答案 2 :(得分:1)

如果您的需求非常具体 - 使用键name1name2合并两个哈希值,那么以下内容应该可以解决问题:

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的答案将起作用,至少如果结构只有两层深度。 如果它可以更深入,你需要一个递归的解决方案。

答案 3 :(得分: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{$_}++ } @_;
}