将元素推入红宝石哈希中的数组中

时间:2011-02-15 20:46:22

标签: ruby arrays hash

在Ruby中,为了创建数组的哈希并将元素推送到这些数组上,我看到了两个成语。我想知道人们更喜欢哪一个,以及为什么。 (披露:我有自己的看法,但我想确保我没有遗漏一些明显的东西。)

方法1:使用Hash的花式初始化器:

ht = Hash.new {|h,k| h[k]=[]}
ht["cats"] << "Jellicle"
ht["cats"] << "Mr. Mistoffelees"

当您使用尚不存在的密钥访问ht时,此方法会创建一个空数组。

方法2:简单的初始化器,花哨的访问器:

ht = {}
(ht["cats"] ||= []) << "Jellicle"
(ht["cats"] ||= []) << "Mr. Mistoffelees"

人们对哪一个更好(或者一个人优先于另一个人的情况)有意见吗?

4 个答案:

答案 0 :(得分:18)

有时哈希最初是用数据填充的,后来它只用于检索数据。在这些情况下,我更喜欢第一种可能性,因为默认的proc可以“清空”(在Ruby 1.9中)。

ht = Hash.new {|h,k| h[k]=[]}
ht["cats"] << "Jellicle"
ht["cats"] << "Mr. Mistoffelees"
ht["dogs"]
p ht
#=> {"cats"=>["Jellicle", "Mr. Mistoffelees"], "dogs"=>[]}

ht.default_proc = proc{}
ht["parrots"] #nil
p ht
#=> {"cats"=>["Jellicle", "Mr. Mistoffelees"], "dogs"=>[]} No parrots!

答案 1 :(得分:2)

如果您事先知道每个键的编号和名称,则可以使用第一个选项。甚至更简单的一个

ht = { "cats" => [] }

否则,如果您不希望(需要)预先初始化哈希,那么第二个选项是一个不错的选择。

答案 2 :(得分:2)

在OP中,我说我有自己的看法。在这里。

尽管“花哨的初始化程序”方法很优雅,但它可能会导致一些非常意外的行为 - 特别是在您不期望它时生成密钥 - 并且通过查看哈希表无法知道这一点。 / p>

请考虑以下事项:

>> ht1 = Hash.new {|h,k| h[k]=[]}
>> ht2 = {}
>> ht1["cats"] << "Jellicle"
=> ["Jellicle"]
>> (ht2["cats"] ||= []) << "Jellicle"
=> ["Jellicle"]

到目前为止一直这么好 - ht1和ht2是完全相同的。但是:

>> ht1["dogs"] ? "got dogs" : "no dogs"
=> "got dogs"
>> ht2["dogs"] ? "got dogs" : "no dogs"
=> "no dogs"

请注意,只需访问ht1 [some_key]即可更改哈希表的状态,即它会创建一个新条目。你可能会争辩说最终用户应该总是使用has_key?()来测试是否存在哈希条目 - 你是对的 - 但上面的用法是一个公认的习惯用法。对于自动创建条目的哈希表,这将是一个意想不到的副作用,因此如果哈希表暴露给最终用户,您应该小心。 (请注意,steenslag的答案显示了如何关闭它。)

答案 3 :(得分:0)

就个人而言,我更喜欢:

ht = Hash.new {|h,k| h[k]=[]}
ht["cats"] << "Jellicle"
ht["cats"] << "Mr. Mistoffelees"

这是对我的维护和自我记录的问题。哈希初始化脏工作发生一次。从那时起,散列中数组的所有赋值都以标准方式进行,这将导致代码看起来正常。

替代方法:

ht = {}
(ht["cats"] ||= []) << "Jellicle"
(ht["cats"] ||= []) << "Mr. Mistoffelees"

看起来很正常,但每个作业都有我所说的#34;视觉噪音&#34;。每次将某些内容推送到散列中的数组时,我们必须在心理上解码||= []的含义。它的精神疲惫,如果你在整个代码中做到这一点,会导致代码不那么优雅,并不断重新评估代码在 THAT 点所做的工作

相关问题