【问题标题】:Perl - Hash::Merge loses keysPerl - Hash::Merge 丢失键
【发布时间】:2021-09-06 17:50:45
【问题描述】:

我正在尝试在 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”会在那里...... 任何想法我做错了什么? 谢谢你的帮助:)

【问题讨论】:

  • 它似乎根本没有合并祝福哈希,尝试将 $hash1 中的顶部键更改为不同的字符串。但是,如果您删除 bless,它就会开始工作。
  • 但是我需要它和祝福一起工作......如果我删除了祝福,我需要在我完成合并时想办法将它归还......并且到处都是祝福哈希值
  • 我想说:对你来说,它们仍然是哈希,但一旦为 Hash::Merge 祝福,它们可能只是另一种不受支持的数据类型。

标签: perl hashmap


【解决方案1】:

Hash::Merge 认为ref 不是HASHARRAY 的任何东西都是标量,并将标量合并规则应用于这些项目(请参阅those lines 的实现Hash::Merge)。合并 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_specget_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 个不同包的情况。您必须为这些实施特殊情况。 (目前尚不清楚合并此类哈希的一般规则是什么)

【讨论】:

  • 感谢您的回复!我收到一个新错误(按照您的代码)。我发布了它here。如果你能看一看,那就太好了。谢谢!
猜你喜欢
  • 2021-11-05
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 2012-04-19
  • 2020-11-28
  • 2020-05-26
相关资源
最近更新 更多