如何在Perl中将哈希插入到另一个哈希中

14

我在主文件的某处定义了一个简单的哈希表

our %translations = (
    "phrase 1" => "translation 1",
    # ... and so on 
    );

在另一个文件中,我想添加更多的翻译。也就是说,我想要做这样的事情:
push our %translations, (
    "phrase N" => "blah-blah",
    # ....
    "phrase M" => "something",
    );

当然这段代码不会起作用:push不能与哈希一起使用。所以我的问题是:有什么简单而优雅的方法将值的哈希插入到现有的哈希中?
我不想求助于...
$translations{"phrase N"} = "blah-blah";
# ....
$translations{"phrase M"} = "something";

由于在Perl中,您应该能够在代码中减少重复...

6个回答

18
%translations = (%translations, %new_translations);

与yi_H答案的原理相同,但展示了您可以在现有哈希表上执行操作,而不仅仅是在创建%translations时这样做。 - plusplus

10

您可以使用keysvalues函数来分配哈希切片。只要在调用之间未修改哈希,keys将以与values返回值相同的顺序返回键。

our %translations = (
  "phrase 1" => "translation 1",
);

{ # Braces just to restrict scope of %add
  my %add = (
    "phrase N" => "blah-blah",
    "phrase M" => "something",
  );
  @translations{keys %add} = values %add;
}

# Or, using your alternate syntax:
@translations{keys %$_} = values %$_ for {
  "phrase N" => "blah-blah",
  "phrase M" => "something",
};

2
太好了!我甚至可以将其编写为@translations{keys %$_} = values $%_ for {"phrase N" => "blah-blah", ...}; - Pasha
1
那种语法我没想到过,但这是一个聪明的捷径。循环可能会使它稍微不那么高效,但我怀疑差异是可以忽略不计的。 - cjm
好的,这是对单个元素进行循环。更多的是一种将匿名哈希分配给 $_ 变量的便捷方式。 - Pasha

8

您可以为哈希切片进行赋值:

@translations{@keys} = @values;

或者使用另一个哈希表中的数据:
@translations{keys %new} = values %new;

然而,由于我正在添加许多新的键,因此很难跟踪键和它们的值之间的对应关系(哪个翻译对应哪个短语)。 - Pasha
@user958624:你可以使用数组作为键和值(请参见更新) - Eugene Yarmash

5
%translations = (
    "phrase N" => "blah-blah",
    # ....
    "phrase M" => "something",
    %translations
    );

这会复制整个哈希表吗?也就是说,假设 %translations 已经包含了数千个条目。你的解决方案会创建一个临时哈希表("phrase N"=>...,"phrase M"=>...,<原始 %translations 的副本>),然后将此临时哈希表分配给 %translations 吗?如果是这样,那么使用此方法将会有显著的开销,如果不是,那么它似乎很简单! - Pasha
@user958624:是的,它确实这样做。从这些子列表构造一个新的列表值,并将其分配给%translations - Eugene Yarmash

2

我知道,这已经说过了。但是我想突出一个方面:

以下操作将覆盖哈希表中现有的值:

%translations = (
    %translations,
    "phrase N" => "blah-blah",
    "phrase M" => "something"
    );

以下内容不包括在内:
%translations = ( 
    "phrase N" => "blah-blah",
    "phrase M" => "something",
    %translations
    );

示例1

my %translations = ( a => 'first', b => 'second');
%translations = (%translations, a => 'at first', c => 'third');

现在你拥有:
"a" => "at first"  # its overwritten by the new value
"b" => "second"
"c" => "third"

例子2

my %translations = ( a => 'first', b => 'second');
%translations = (a => 'at first', c => 'third', %translations);

现在您拥有的是:
"a" => "first"  # the old value is not overwritten
"b" => "second"
"c" => "third"

2
Hash::Merge 是另一种选择:https://metacpan.org/module/Hash::Merge 并且不要太担心复制哈希表的优化问题,如果它成为一个问题,在那时再进行研究。首先尝试编写良好、清晰易懂和易于维护的代码。具有字符串值的数千个键的哈希表并不大!
你在问题中没有说明的是键是否会发生冲突(即从文件中读取的两个“Phrase 1”是否可能相同)。

Hash::Merge 只有在你有嵌套的数据结构或需要对重复键进行特殊处理时才是过度设计。 - cjm
1
我同意,在这种情况下确实如此,但知道它的存在是有用的,所以我想提一下。 - plusplus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接