在Ruby中创建哈希哈希允许方便的两个(或更多)维度查找.但是,插入时必须始终检查散列中是否已存在第一个索引.例如:
h = Hash.new
h['x'] = Hash.new if not h.key?('x')
h['x']['y'] = value_to_insert
Run Code Online (Sandbox Code Playgroud)
最好在自动创建新哈希的情况下执行以下操作:
h = Hash.new
h['x']['y'] = value_to_insert
Run Code Online (Sandbox Code Playgroud)
类似地,当查找第一个索引尚不存在的值时,如果返回nil而不是接收"[]"错误的未定义方法,则更为可取.
looked_up_value = h['w']['z']
Run Code Online (Sandbox Code Playgroud)
可以创建一个具有此行为的Hash包装类,但是是否存在用于完成此任务的Ruby习惯用法?
我是一个Perl人,我已经做了一段时间的哈希:
my %date;
#Assume the scalars are called with 'my' earlier
$date{$month}{$day}{$hours}{$min}{$sec}++
现在我正在学习Ruby,到目前为止我发现使用这个树是做许多键和值的方法.有没有办法使用我用Perl使用一行的简单格式?
@date = {
month => {
day => {
hours => {
min => {
sec => 1
}
}
}
}
}
有什么比这简单的方法
if hash.key?('a')
hash['a']['b'] = 'c'
else
hash['a'] = {}
hash['a']['b'] = 'c'
end
Run Code Online (Sandbox Code Playgroud) ruby hash variable-assignment autovivification hash-of-hashes
这是一个聪明的技巧,在ruby中启用哈希自动修复(取自facet):
# File lib/core/facets/hash/autonew.rb, line 19
def self.autonew(*args)
leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
new(*args,&leet)
end
Run Code Online (Sandbox Code Playgroud)
虽然它有效(当然),但我发现我无法弄清楚这两个衬垫是如何做到的.
leet被置为默认值.所以,然后只是h['new_key']以某种方式访问它,并创建'new_key' => {}
现在,我希望h['new_key']返回默认值对象而不是评估它.也就是说,'new_key' => {}不会自动创建.那么leet实际上是如何被调用的呢?特别是有两个参数?
为了实现Ruby哈希的自动生成,可以使用以下类
class AutoHash < Hash
def initialize(*args)
super()
@update, @update_index = args[0][:update], args[0][:update_key] unless
args.empty?
end
def [](k)
if self.has_key?k
super(k)
else
AutoHash.new(:update => self, :update_key => k)
end
end
def []=(k, v)
@update[@update_index] = self if @update and @update_index
super
end
def few(n=0)
Array.new(n) { AutoHash.new }
end
end
Run Code Online (Sandbox Code Playgroud)
该类允许执行以下操作
a = AutoHash.new
a[:a][:b] = 1
p a[:c] # => {} # key :c has not been created
p a # => {:a=>{:b=>1}} # note, that it does not …Run Code Online (Sandbox Code Playgroud)