在ruby中访问嵌套哈希的元素 [英] Accessing elements of nested hashes in ruby

查看:162
本文介绍了在ruby中访问嵌套哈希的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个用ruby编写的实用程序,它广泛使用嵌套哈希。目前,我正在检查对嵌套散列元素的访问,如下所示:

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

#我想要structure [:a] [:b]

value = nil

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

有没有更好的方法来做到这一点?我希望能够说:

$ p $ value = structure [:a] [:b]

获得 nil 如果:a不是 structure

解决方案

我通常这样做的方式是:

  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'] - > {}

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



编辑:更多详细信息

Ruby哈希允许您控制在查找新密钥时如何创建默认值。指定时,此行为被封装为 Proc 对象,并可通过 default_proc default_proc = 方法。默认的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_hash default_proc 。该块传递两个对象: h ,这是执行密钥查找的 Hash 实例,而<

第2行将散列中的默认值设置为一个新的<$ c k ,该键被查找。 $ c> Hash 实例。这个散列的缺省行为是通过传递从 default_proc 创建的 Proc ;即,块本身正在定义的默认proc。



以下是IRB会话的示例:

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

recursive_hash [ :foo] 被创建,它的 default_proc recursive_hash 的<$ c提供$ C> default_proc 。这有两个作用:


  1. recursive_hash [:foo] 的默认行为是与相同。recursive_hash

  2. recursive_hash [:foo] default_proc 将与 recursive_hash 相同。

  3. ol>

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

      irb主要):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 => {}}}}


    I'm working a little utility written in ruby that makes extensive use of nested hashes. Currently, I'm checking access to nested hash elements as follows:

    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
    

    Is there a better way to do this? I'd like to be able to say:

    value = structure[:a][:b]
    

    And get nil if :a is not a key in structure, etc.

    解决方案

    The way I usually do this these days is:

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

    This will give you a hash that creates a new hash as the entry for a missing key, but returns nil for the second level of key:

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

    You can nest this to add multiple layers that can be addressed this way:

    h = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = {} } }
    
    h['bar'] -> {}
    h['tar']['zar'] -> {}
    h['scar']['far']['mar'] -> nil
    

    You can also chain indefinitely by using the default_proc method:

    h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
    
    h['bar'] -> {}
    h['tar']['star']['par'] -> {}
    

    The above code creates a hash whose default proc creates a new Hash with the same default proc. So, a hash created as a default value when a lookup for an unseen key occurs will have the same default behavior.

    EDIT: More details

    Ruby hashes allow you to control how default values are created when a lookup occurs for a new key. When specified, this behavior is encapsulated as a Proc object and is reachable via the default_proc and default_proc= methods. The default proc can also be specified by passing a block to Hash.new.

    Let's break this code down a little. This is not idiomatic ruby, but it's easier to break it out into multiple lines:

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

    Line 1 declares a variable recursive_hash to be a new Hash and begins a block to be recursive_hash's default_proc. The block is passed two objects: h, which is the Hash instance the key lookup is being performed on, and k, the key being looked up.

    Line 2 sets the default value in the hash to a new Hash instance. The default behavior for this hash is supplied by passing a Proc created from the default_proc of the hash the lookup is occurring in; ie, the default proc the block itself is defining.

    Here's an example from an IRB session:

    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=>{}}
    

    When the hash at recursive_hash[:foo] was created, its default_proc was supplied by recursive_hash's default_proc. This has two effects:

    1. The default behavior for recursive_hash[:foo] is the same as recursive_hash.
    2. The default behavior for hashes created by recursive_hash[:foo]'s default_proc will be the same as recursive_hash.

    So, continuing in IRB, we get the following:

    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中访问嵌套哈希的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆