0

我必须散列如下:

my %hash1 = (
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst2' => 2,
                        'inst0' => 0
                    }
                }
            }
        }
    }
);

my %hash2 = (
    'modules' => {
        'sub_top' => {
            'instances' => {
                'inst0' => 0,
                'inst1' => 1
            }
        }
    }
);                                                                   }

我需要将这些合并到一个哈希中。我尝试使用 Hash::Merge 但这仅在我从 subtop 开始时才有效。

my $merged_hash = merge(\%{$hash1{modules}{top0}{instances}}, \%{$hash2{modules}});

倾倒结果$merged_hash给出:

$VAR1 = {
    'sub_top' => {
        'instances' => {
            'inst2' => 2,
            'inst0' => 0,
            'inst1' => 1
        }
    }
};

但我错过了 hash1 的顶部:

'modules' => {
    'top0' => {
        'instances' => {

合并后所需的哈希应该是这样的:

$VAR1 = {
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst2' => 2,
                        'inst0' => 0,
                        'inst1' => 1
                    }
                }
            }
        }
    }
};
4

2 回答 2

3

在预定义键上合并散列的一种可能方法。看看它是否满足你的期望。

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $debug = 0;

my %hash1 = (
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst2' => 2,
                        'inst0' => 0
                    }
                }
            }
        }
    }
);

my %hash2 = (
    'modules' => {
        'sub_top' => {
            'instances' => {
                'inst0' => 0,
                'inst1' => 1
            }
        }
    }
); 

my $key = 'sub_top';

mergeOnKey(\%hash1, \%hash2, $key);

say Dumper(\%hash1);

sub mergeOnKey {
    my $h1 = shift;
    my $h2 = shift;
    my $k  = shift;

    my $href1 = find_ref($h1,$k);
    my $href2 = find_ref($h2,$k);

    die 'Hash 1 no key was found' unless $href1;
    die 'Hash 2 no key was found' unless $href2;

    merge($href1,$href2);
}

sub merge {
    my $href1 = shift;
    my $href2 = shift;

    foreach my $key (keys %{$href2}) {
        if( ref $href2->{$key} eq ref {} ) {
            merge($href1->{$key},$href2->{$key});
        } else {
            $href1->{$key} = $href2->{$key} unless defined $href1->{$key};
        }
    }

    say Dumper($href1) if $debug;
}

sub find_ref {
    my $href = shift;
    my $key  = shift;

    while( my($k,$v) = each %{$href} ){
        say Dumper($v) if $debug;
        return $v if $k eq $key;
        return find_ref($v,$key) if ref $v eq 'HASH';
    }

    return 0;
}

输出

$VAR1 = {
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst1' => 1,
                        'inst2' => 2,
                        'inst0' => 0
                    }
                }
            }
        }
    }
};
于 2020-02-13T02:15:47.783 回答
1

如果您查看Hash::Merge 的概要,则该示例显示了两个在结构上看起来几乎相同的哈希。您要合并的哈希可能有许多相似之处,但它们也有显着差异。所以,我只希望你只能在它们的结构足够“等效”的地方合并它们。这是我能想到的让它们合并到您指示的结果哈希的最明显方法:

#!/bin/env perl
use strict;
use warnings;
use Test::More;    
use Hash::Merge qw(merge);

my %hash1 = (
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst2' => 2,
                        'inst0' => 0
                    }
                }
            }
        }
    }
);

my %hash2 = (
    'modules' => {
        'sub_top' => {
            'instances' => {
                'inst0' => 0,
                'inst1' => 1
            }
        }
    }
);

# Merge the desired parts of the structure
$hash1{modules}{top0}{instances} =
  merge( \%{ $hash1{modules}{top0}{instances} }, \%{ $hash2{modules} } );

# Demonstrate that merge worked as desired
my %desired = (
    'modules' => {
        'top0' => {
            'instances' => {
                'sub_top' => {
                    'instances' => {
                        'inst2' => 2,
                        'inst0' => 0,
                        'inst1' => 1
                    }
                }
            }
        }
    }
);

is_deeply( \%hash1, \%desired, 'Desired hash is created' );

done_testing();
于 2020-02-12T22:17:59.500 回答