在perl中组合2个“深”(多维)哈希

时间:2012-11-06 12:26:10

标签: perl hash merge hash-of-hashes

有一个问题可以在这里解释我想要的内容:how to merge 2 deep hashes in perl

然而,那里的答案似乎对我不起作用(使用Merge模块的建议)。

我有两个像这样的哈希:

$VAR1 = {
          '57494' => {
                       'name' => 'John Smith',
                       'age' => '9',
                       'height' => '120'
                     },
          '57495' => {
                       'name' => 'Amy Pond',
                       'age' => '17',
                       'height' => '168'
                     }
        }
};
$VAR1 = {
          '57494' => {
                       'name_address' => 'Peter Smith',
                       'address' => '5 Cambridge Road',
                       'post_code' => 'CR5 0FS'
                     }
        }
};

如果我使用Hash::Merge%c = {%a,%b}格式,我每次都会这样:

$VAR1 = '57494';
$VAR2 = {
          'name_address' => 'Peter Smith',
          'address' => '5 Cambridge Road',
          'post_code' => 'CR5 0FS'
        };

(所以它基本上用第二个数据覆盖了第一个数据并弄乱了键)我想要:

$VAR1 = {
          '57494' => {
                       'name' => 'John Smith',
                       'age' => '9',
                       'height' => '120'
                       'name_address' => 'Peter Smith',
                       'address' => '5 Cambridge Road',
                       'post_code' => 'CR5 0FS'
                     },
          '57495' => {
                       'name' => 'Amy Pond',
                       'age' => '17',
                       'height' => '168'
                     }
        }
};

因此,当键相同时,数据会合并在一起,否则新键只会附加到末尾。我希望这是有道理的。也许我使用Merge做了错误的事情,或者需要“手动”将它们添加到循环中,但无论如何我都会花太多时间思考它!

编辑:我如何使用Merge来查看我是否正在做一些愚蠢的事情:

我有:

use Hash::Merge qw( merge );

...hash data above as %hash1 and %hash2...

my %combined_hash = %{ merge( %hash1,%hash2 ) };
print Dumper(%combined_hash);

2 个答案:

答案 0 :(得分:7)

如果我使用引用,它就像一个魅力。

use strict; use warnings;
use Data::Dumper;
use Hash::Merge qw(merge);
my $h1 = {
  '57494' => {
    'name'   => 'John Smith',
    'age'    => '9',
    'height' => '120'
  },
  '57495' => {
    'name'   => 'Amy Pond',
    'age'    => '17',
    'height' => '168'
  }
};

my $h2 = {
  '57494' => {
    'name_address' => 'Peter Smith',
    'address'      => '5 Cambridge Road',
    'post_code'    => 'CR5 0FS'
  }
};

my $h3 = merge( $h1, $h2 );
print Dumper $h3;

输出:

$VAR1 = {
      '57495' => {
                   'name' => 'Amy Pond',
                   'age' => '17',
                   'height' => '168'
                 },
      '57494' => {
                   'name_address' => 'Peter Smith',
                   'name' => 'John Smith',
                   'post_code' => 'CR5 0FS',
                   'address' => '5 Cambridge Road',
                   'height' => '120',
                   'age' => '9'
                 }
    };

但是,如果我使用散列而不是散列引用来执行此操作,则不会:

my %hash1 = (
  '57494' => {
    'name'   => 'John Smith',
    'age'    => '9',
    'height' => '120'
  },
  '57495' => {
    'name'   => 'Amy Pond',
    'age'    => '17',
    'height' => '168'
  }
);

my %hash2 = (
  '57494' => {
    'name_address' => 'Peter Smith',
    'address'      => '5 Cambridge Road',
    'post_code'    => 'CR5 0FS'
  }
);

my %h3 = merge( %hash1, %hash2 );
print Dumper \%h3;

__END__
$VAR1 = {
  '57495' => undef
};

这是因为Hash::Merge中的merge只能接受引用,但是你传递的是哈希值。此外,您需要在标量上下文中调用它。

尝试如下:

#                             +--------+--- references
#   ,-- SCALAR context        |        |
my $combined_hash = %{ merge( \%hash1, \%hash2 ) };
print Dumper($combined_hash);

答案 1 :(得分:1)

for my $key (keys %fromhash) {
    if(not exists $tohash{$key}) {
        $tohash{$key} = {};
    }
    for my $subkey (keys %{$fromhash{$key}}) {
        ${$tohash{$key}}{$subkey} = ${$fromhash{$key}}{$subkey};
    }
}

根据我的最后一杯咖啡是否有用,或多或少的支撑。

Python对于这种事情肯定更舒服,因为它不会让你考虑引用:

for key in fromdict:
    if key not in todict:
        todict[key] = {}
    todict[key] = dict(fromdict[key].items() + todict[key].items())

或者todictdefaultdict(在阅读和分配时创建关键字):

for key in fromdict:
    todict[key] = dict(dict(fromdict[key]).items() + dict(todict[key]).items())