合并两个或更多个散列片,即仅从散列中选择的键

时间:2016-01-13 17:24:33

标签: perl merge hashmap perl-data-structures

我正在编写一段接收参数%args且配置为%conf的代码。我需要将某些值这两个哈希传递到另一个Perl模块,而其他值仅与我自己的代码相关。

如何以优雅的方式合并两个(或多个)哈希切片合并哈希,同时仅保留选定的密钥

重点:

  • 所需密钥列表可用作列表或保存在数组中。
  • 来自%args的值将覆盖%conf
  • 中的值
  • %args中未包含的密钥和%conf中未包含的密钥不得包含在%result中。

示例输入:

my %conf = (
     path  => '/usr/local/bin/',
     size  => 42,
     other => 'value', # isn't used
);
my %args = (
     path => '~/bin/', # overrides $conf{path}
     foo  => 'bar',
);
my @keys = qw<path size foo bar>;  # 'bar' isn't contained in either hash!

预期结果:

my %result = (
    path => '~/bin/', # from $args{patħ}
    size => 42,
    foo  => 'bar',
);

对于简单的合并,这就足够了:

my %result = ( %conf, %args );

简单的哈希切片也很简单:

my %slice = map { $_ => $hash{$_} } qw<foo bar baz>;

缩减到现有密钥已经需要一个临时变量:

my %keys = map { $_ => 1 } qw<foo bar baz>;
grep { $keys{$_} } %hash;

但总而言之,变得非常复杂:

my @keys = qw<foo bar baz>;
my %keys = map { $_ => 1 } @keys;
my %result = (
    map( { $_ => $conf{$_} } grep { $keys{$_} } keys %conf ),
    map( { $_ => $args{$_} } grep { $keys{$_} } keys %args ),
);

有没有更好的方法来编码?

1 个答案:

答案 0 :(得分:1)

更新

这是对您修改过的问题的回复。我尽最大努力写一些干净的东西只删除不在@keys中的组合哈希的任何元素,使用中间%wanted哈希来描述在数组中出现哪些哈希键

use strict;
use warnings 'all';


# Set up test data

my %conf = (
     path  => '/usr/local/bin/',
     size  => 42,
     other => 'value', # isn't used
);

my %args = (
     path => '~/bin/', # overrides $conf{path}
     foo  => 'bar',
);

my @keys = qw/ path size foo bar /;  # 'bar' isn't contained in either hash!


# Combine and select

my %wanted = map { $_ => 1 } @keys;

my %result = (%conf, %args);
delete @result{ grep { not $wanted{$_} } keys %result };


# Display the result

use Data::Dump;
dd \%result;

输出

{ foo => "bar", path => "~/bin/", size => 42 }


原始

这似乎符合法案。我已经从您的帖子中复制了测试数据

  • 将两个哈希值合并到%join%args覆盖%conf,将其放在列表分配中第二位

  • 然后使用切片从%result

  • 中提取所需的元素,从而构建数组%join
  • 我只使用Data::Dump来显示上述代码的结果

  • 请注意,如果@keys中的字符串未出现在 哈希中,则它将包含在%results中且值为undef

  • “所需密钥列表可用作列表或保存在数组中。”

    这是一个非常模糊的要求。要使此解决方案起作用,您需要一组键,因此只需将列表存储为数组


use strict;
use warnings 'all';


# Set up test data

my %conf = (
     path  => '/usr/local/bin/',
     size  => 42,
     other => 'value', # isn't used
);

my %args = (
     path => '~/bin/', # overrides $conf{path}
     foo  => 'bar',
);

my @keys = qw/ path size foo /;


# Combine and select

my %join = (%conf, %args);

my %result;
@result{@keys} = @join{@keys};


# Display the result

use Data::Dump;
dd \%result;

输出

{ foo => "bar", path => "~/bin/", size => 42 }