从Ruby中的键数组中获取哈希值的方法

时间:2014-08-12 03:00:05

标签: ruby arrays hash

我正在尝试编写一个返回哈希键值的函数,当提供一个键数组时(如果键不存在则为'nil')。

考虑哈希:

my_hash = { 
  font_size: 10, 
  font_family: "Arial", 
  boo: { 
    name: 'blah' 
  } 
}

方法的存根可能是:

def get_value(hash, array_of_keys)
  ...
end

原因是我可以访问哈希中可能实际不存在的不同键。因此,例如,我想要'等等',通常我会打电话给my_hash[:boo][:name],但它可能不存在或者可能非常深。我想要做的是拥有我的函数,我可以使用get_value(my_hash, [:boo, :name])调用,以便我可以测试每个密钥是否存在(因此,如果它们中的任何一个不存在,我不会得到异常,并且它不会这个价值可能有多“深”。

在我的情况下,检查我需要的每个值的存在是不可行的(我可能需要测试10个连续键的存在)我只需要一个函数,我可以说我需要哪个值并获取值,如果它存在,如果不存在,则为nil(因此不会尝试检索异常)。

我试了一下,尝试使用递归函数'每次循环时弹出数组中的第一个元素,但我无法锻炼如何返回我的值。

def get_value(val, arr)
  if arr.count > 1
    arr.each do |a|
      get_value val[a], arr.pop
    end
  else
    val[a]
  end
end


get_value s, [:boo, :name]

这是我的尝试(显然不起作用) - 任何人都可以帮我解决这个问题,或者有一个可能更优雅的替代解决方案吗?几点:

  • 密钥不保证存在,我想返回nil in 那些案件,和
  • 哈希可能非常深,所以它需要处理数组中的任何哈希和任意数量的键(这就是为什么我认为递归可能是答案,但现在我不太确定)。

3 个答案:

答案 0 :(得分:4)

[:font_size].inject(my_hash){|h, k| h.to_h[k]} #=> 10
[:boo, :name].inject(my_hash){|h, k| h.to_h[k]} #=> "blah"
[:boo, :foo].inject(my_hash){|h, k| h.to_h[k]} #=> nil

答案 1 :(得分:1)

class Hash
    def get_value(array_of_keys)
        return nil unless array_of_keys.is_a? Array
        return nil if array_of_keys.empty?
        return nil unless self.has_key? array_of_keys.first

        if self[array_of_keys.first].is_a? Hash
            self[array_of_keys.first].get_value(array_of_keys[1..-1])
        else
            self[array_of_keys.first]
        end
    end
end


my_hash = { 
  font_size: 10, 
  font_family: "Arial", 
  boo: { 
    name: 'blah' 
  } ,
  radley: {
    one: {
        more: {
            time: 'now'
        }
    }
  }
}

p my_hash.get_value [:boo, :name]

p my_hash.get_value [:radley, :one, :more, :time]

p my_hash.get_value [:radley, :one, :other, :time]

说明

我将该方法直接添加到Hash类,以便您可以将其作为现有哈希值的实例方法(使其更好用)。

该方法获取数组,如果参数实际上不是数组,则返回nil,如果数组为空,则返回nil,如果Hash不包含与数组的第一个元素匹配的键。

接下来,检查该密钥的值本身是否为Hash

如果是这样,请在Hash上使用数组的其余部分调用此方法!

如果值不是哈希值,则返回该值。

答案 2 :(得分:1)

我使用递归来刺伤它:

def get_value(hash, keys_array)
  key = keys_array.shift
  if hash.has_key? key
    if hash[key].is_a?(Hash) && keys_array.size >= 1
      get_value(hash[key], keys_array)
    else
      hash[key]
    end
  else
    nil
  end
end
  1. 我从keys_array
  2. 中删除第一个键
  3. 我检查Hash中是否存在该密钥
  4. 如果是,我检查该键的值是否为哈希,并且我们仍然在数组中保留键,如果是这种情况,我调用带有该值的方法并保留键数组
  5. 如果它不是哈希,我只返回值
  6. 如果密钥不存在,请返回nil
  7. 顺便说一句好问题:)