我有几个变量,例如年,月,日,小时,分钟< / strong>即可。我需要对嵌套哈希进行一些操作,使用hash[2012][12][12][4][3]
这些值。当遇到新的日期时,我需要扩展哈希值。
我可以通过判断每个级别逐个来完成此操作,并创建一个哈希(如果不存在)。但我想知道有一种方便的方法。
在perl中,我可以调用$hash{$v1}{$v2}{$v3}..{$vN} = something
,因为默认情况下可以创建未定义的哈希值。
答案 0 :(得分:1)
我同意sawa的评论。这种方法可能会有许多其他问题。但是,你想要的是什么。
搜索“ruby哈希默认值”。
默认情况下,哈希条目的默认值为nil
。你可以改变它,即:
h = Hash.new(5)
现在h
被要求提供不存在的密钥时将返回5,而不是nil。您可以命令它以类似的方式返回一个新的空数组或新的空哈希。
但是,要小心。很容易意外地通过所有条目共享默认实例。
h = Hash.new([]) // default value = Array object, let's name it X
one = h[:dad] // returns THE SAME object X
two = h[:mom] // returns THE SAME object X
您必须小心不要使用shared-default-instance,并使用不会改变它的操作。你不能只是
h[:mom] << 'thing'
因为h[:brandnewone]
现在将返回带有“thing”的变异默认实例。
答案 1 :(得分:1)
您可以添加一个辅助方法,您可能会发现它在其他环境中很有用:
def mfetch(hash, *keys)
return nil if (keys.empty? || !hash[keys.first])
return hash[keys.first] if keys.size == 1
k = keys.shift
raise ArgumentError, "Too many keys" unless hash[k].is_a? Hash
return mfetch(hash[k], *keys)
end
h = {cat: {dog: {pig: 'oink'}}} # => {:cat=>{:dog=>{:pig=>"oink"}}}
mfetch(h, :cat, :dog, :pig) # => "oink"
mfetch(h, :cat, :dog) # => {:pig=>"oink"}
mfetch(h, :cat) # => {:dog=>{:pig=>"oink"}}
mfetch(h, :cow) # => nil
mfetch(h, :cat, :cow) # => nil
mfetch(h, :cat, :dog, :cow) # => nil
mfetch(h, :cat, :dog, :pig, :cow) # => ArgumentError: Too many keys
如果您愿意,可以将方法添加到Hash类中:
class Hash
def mfetch(*keys)
return nil if (keys.empty? || !hash[keys.first])
return self[keys.first] if keys.size == 1
k = keys.shift
raise ArgumentError, "Too many keys" unless self[k].is_a? Hash
return self[k].mfetch(*keys)
end
end
h.mfetch(:cat, :dog, :pig) # => "oink"
或者如果您使用的是Ruby 2.0,请将class Hash
替换为refine Hash do
以限制对当前类的添加。将它放在要包含的模块中可能会很方便。