我正在使用一个用ruby编写的小实用程序,它广泛使用嵌套哈希.目前,我正在判断对嵌套哈希元素的访问,如下所示:

structure = { :a => { :b => 'foo' }}

# I want structure[:a][:b]

value = nil

if structure.has_key?(:a) && structure[:a].has_key?(:b) then
  value = structure[:a][:b]
end

有更好的方法吗?我想说:

value = structure[:a][:b]

如果:a不是structure中的键,则得到nil,以此类推.

推荐答案

这些天我通常的做法是:

h = Hash.new { |h,k| h[k] = {} }

这将为您提供一个散列,该散列创建一个新的散列作为缺少的密钥的条目,但为第二级密钥返回nil:

h['foo'] -> {}
h['foo']['bar'] -> nil

您可以将其嵌套以添加多个层,这些层可以通过以下方式寻址:

h = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = {} } }

h['bar'] -> {}
h['tar']['zar'] -> {}
h['scar']['far']['mar'] -> nil

您还可以使用default_proc方法无限期链接:

h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

h['bar'] -> {}
h['tar']['star']['par'] -> {}

上面的代码创建了一个散列,其默认进程使用相同的默认进程创建了一个新的散列.因此,当查找不可见的密钥时,作为默认值创建的哈希将具有相同的默认行为.

EDIT: More details

Ruby哈希允许您控制在查找新键时如何创建默认值.如果指定,此行为将封装为Proc对象,并可通过default_procdefault_proc=方法访问.也可以通过向Hash.new传递一个块来指定默认进程.

让我们把这个代码分解一下.这不是惯用的ruby,但更容易将其分成多行:

1. recursive_hash = Hash.new do |h, k|
2.   h[k] = Hash.new(&h.default_proc)
3. end

第1行将变量recursive_hash声明为新的Hash,并将块开始为recursive_hashdefault_proc.块被传递给两个对象:h,这是正在执行密钥查找的Hash实例,k,这是正在查找的密钥.

第2行将哈希中的默认值设置为新的Hash实例.该散列的默认行为是通过传递一个Proc来提供的,该Proc是根据正在查找的散列的default_proc创建的;即,块本身定义的默认过程.

以下是IRB会议的一个例子:

irb(main):011:0> recursive_hash = Hash.new do |h,k|
irb(main):012:1* h[k] = Hash.new(&h.default_proc)
irb(main):013:1> end
=> {}
irb(main):014:0> recursive_hash[:foo]
=> {}
irb(main):015:0> recursive_hash
=> {:foo=>{}}

创建recursive_hash[:foo]处的散列时,其default_procrecursive_hashdefault_proc提供.这有两个影响:

  1. recursive_hash[:foo]的默认行为与recursive_hash相同.
  2. recursive_hash[:foo]default_proc创建的哈希的默认行为与recursive_hash相同.

因此,继续IRB,我们得到以下结果:

irb(main):016:0> recursive_hash[:foo][:bar]
=> {}
irb(main):017:0> recursive_hash
=> {:foo=>{:bar=>{}}}
irb(main):018:0> recursive_hash[:foo][:bar][:zap]
=> {}
irb(main):019:0> recursive_hash
=> {:foo=>{:bar=>{:zap=>{}}}}

Ruby相关问答推荐

使用Mac命令行解密用Ruby加密的Zip

如何将包含换行符(和可能其他特殊字符)的Ruby字符串转义为有效的shell变量值?

Ruby中带和不带下划线_的方法参数有什么区别

如何在 Ruby 中生成一个包含 n 个唯一随机数的列表?

为什么 Ruby 中的 `a = a` `nil`?

方法如何在 Ruby 中使用哈希参数?

Ruby:如何卸载设计(uninstall Devise)?

从 Ruby 程序中创建 beep声的最简单方法是什么?

你喜欢哪种风格的 Ruby 字符串引用?

将字符串与多个模式匹配

如何在 ruby​​ 中针对正则表达式测试整个字符串?

从字符串中删除所有特殊字符 - ruby

在不同的换行符上拆分

如何在Ruby中对数组中对象的属性求和

通过 x 个字符在 Ruby 中获取子字符串

gem 安装失败并出现 openssl 失败

在 Ruby 中,获取数组中最大值的索引的最简洁方法是什么?

如何使用 Ruby 运行命令五次?

OpenSSL vs GPG 用于加密异地备份?

Ruby哈希中的条件键/值