我正在尝试在 Perl 中合并两个受祝福的哈希值。
我正在运行以下代码:
#!usr/bin/perl
use strict;
use warnings;
use Hash::Merge;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
my $hash1 = bless( {
'CalcPorts' => {
'helper_1' => {
'Scope' => [
''
],
},
'helper_2' => {
'Scope' => [
''
],
},
},
}, 'IB' );
my $hash2 = bless( {
'CalcPorts' => {
'helper_2' => {
'Scope' => [
'd'
],
},
},
}, 'IB' );
my $merger = Hash::Merge->new('LEFT_PRECEDENT');
my $hash3 = $merger->merge($hash2, $hash1);
print Dumper($hash3);
输出是这样的:
$VAR1 = bless( {
'CalcPorts' => {
'helper_2' => {
'Scope' => [
'd'
]
}
}
}, 'IB' );
尽管我预计“helper_1”会在那里...... 有什么想法我做错了什么吗? 感谢您的帮助:)
最佳答案
Hash::Merge
认为 ref
不是 HASH
或 ARRAY
的任何内容都是标量,并对这些项应用标量合并规则(请参阅 Hash::Merge
实现的 those lines)。合并 2 个标量时,Hash::Merge
要么丢弃其中一个,要么创建一个数组来存储它们。这些选项都不会合并祝福的哈希值。
要解决这个问题,您可以先取消哈希值的祝福(例如使用 Data::Structure::Util::unbless
),然后合并它们,然后重新祝福它们:
use Data::Structure::Util qw(unbless);
my $class = ref $hash1;
unbless $hash1;
unbless $hash2;
my $hash3 = bless $merger->merge($hash2, $hash1), $class;
如果您的主哈希中有受祝福的哈希,那么您可以使用 add_behavior_spec
定义您自己的 Hash::Merge
行为。方法:对于 SCALAR
-SCALAR
情况,检查两个标量是否都是被祝福的引用,如果是,则 unbless、merge 和 rebless:
$merger->add_behavior_spec(
{ 'SCALAR' => {
'SCALAR' => sub {
my $self = &Hash::Merge::_get_obj;
my ($left, $right) = @_;
my ($class_left, $class_right) = (ref $left, ref $right);
if ($class_left && $class_left eq $class_right) {
unbless $left;
unbless $right;
return bless $self->merge($left, $right), $class_left;
} else {
return $_[1]; # Or something else
}
},
'ARRAY' => ...,
'HASH' => ...,
},
ARRAY => { ... },
HASH => { ... }
为了简洁起见,我为不相关的情况留下了...
。您可以复制粘贴 the source of Hash::Merger
中的内容(选择您想要的行为)。或者,也许更简单,您可以使用 get_behavior_spec
和 get_behavior
更改当前行为的 SCALAR
-SCALAR
情况的方法:
my $behavior = $merger->get_behavior_spec($merger->get_behavior);
my $old_behavior_scalar_scalar = $behavior->{SCALAR}{SCALAR};
$behavior->{SCALAR}{SCALAR} = sub {
my $self = &Hash::Merge::_get_obj;
my ($left, $right) = @_;
my ($class_left, $class_right) = (ref $left, ref $right);
if ($class_left && $class_left eq $class_right) {
unbless $left;
unbless $right;
return bless $self->merge($left, $right), $class_left;
} else {
# Regular scalars, use old behavior
return $old_behavior_scalar_scalar->($left, $right);
}
};
请注意,这不能很好地处理您想要合并 2 个受祝福的 2 个不同包的哈希值的情况。您必须为这些实现特殊情况。 (尚不清楚合并此类哈希的一般规则是什么)
关于Perl - Hash::Merge 丢失 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69071202/