是否有更好的Ruby或Rails习惯用于检查嵌套哈希中是否存在值?

时间:2013-09-16 19:30:30

标签: ruby-on-rails ruby hash

如果值:

myhash['first_key']['second_key']

存在,然后我需要得到它。但'second_key'中可能根本不存在my_hash,如果不是,我也不希望该行引发异常。

现在我正在用一个丑陋的条件包装整件事情:

if myhash['first_key'].present? and myhash['first_key']['second_key'].present?
  ...
end

我确定必须有更简单的东西。

6 个答案:

答案 0 :(得分:8)

您始终可以使用try

hsh.try(:[], 'first_key').try(:[], 'second_key')

仅供参考:如果您正在进行大量此类检查,您可能需要重构代码以避免这些情况。

答案 1 :(得分:4)

如有疑问,请写一个包装器:

h = {
  first_key: {
    second_key: 'test'
  }
}

class Hash
  def fetch_path(*parts)
    parts.reduce(self) do |memo, key|
      memo[key] if memo
    end
  end
end

h.fetch_path(:first_key, :second_key) # => "test"
h.fetch_path(:first_key, :third_key) # => nil
h.fetch_path(:first_key, :third_key, :fourth_key) # => nil
h.fetch_path(:foo, :third_key) # => nil

答案 2 :(得分:4)

尝试这种干净整洁的解决方案。哈希默认值:

h = Hash.new( {} ) # sets a hash as default value

现在做你喜欢的事:

h[:some_key] # => {}
h[:non_existent_key][:yet_another_non_existent_key] # => nil

尼斯?

假设您有一个已填充的现有哈希:

h = { a: 1, b: 2, c: 3 }

所以你只需将其默认设置为返回一个新哈希:

h.default = {}

然后你又去了:

h[:d] # => {}
h[:d][:e] # => nil

答案 3 :(得分:1)

我会指向优秀的Hashie::Mash

一个例子:

mash = Hashie::Mash.new

# Note: You used to be able to do : `mash.hello.world` and that would return `nil`
# However it seems that behavior has changed and now you need to use a `!` :

mash.hello!.world # => nil  # Note use of `!`


mash.hello!.world = 'Nice'  # Multi-level assignment!


mash.hello.world # => "Nice"
# or
mash.hello!.world # => "Nice"

答案 4 :(得分:0)

您可以在处理哈希之前设置一些默认值。类似的东西:

myhash[:first_key] ||= {}

if myhash[:first_key][:second_key]
  # do work
end

答案 5 :(得分:0)

为什么不为此定义方法?

class Hash
  def has_second_key?(k1,k2)
    self[k1] ? self[k1][k2] : nil
  end
end
new_hash = {}
new_hash["a"] = "b"
new_hash["c"] = {"d"=>"e","f"=>"g"}
new_hash[:p] = {q:"r"}
new_hash.has_second_key?("r","p")
  # =>nil
new_hash.has_second_key?("c","f")
  # =>"g"
new_hash.hash_second_key?(:p,:q)
  # =>"r"

要修改您的代码,它将是:

if myhash.has_second_key?('first-key','second-key') 
  ...
end

此方法将返回nil,在Ruby中为Falsey,或者将返回Ruby中Truthy的第二个键的值。

显然,如果您不想修改Hash类,则无需修改。您可以使用除哈希之外的方法作为参数。 has_second_key?(hash,k1,k2)。然后将其称为:

has_second_key?(myhash,'first-key','second-key')