ruby可以深入搜索特定键的哈希/数组吗?

时间:2014-05-13 16:02:25

标签: ruby arrays json api hash

我有一些ruby代码从Jenkins获取一个包含n个项目数组的json。我想要的项目有一个名为" lastBuiltRevision"

的密钥

我知道我可以像这样循环遍历数组

actions.each do |action| 
    if action["lastBuiltRevision"]
        lastSuccessfulRev = action["lastBuiltRevision"]["SHA1"]
        break
    end
end

但是这种感觉非常笨重,并且没有我在使用红宝石时通常会感受到的魔力。

我现在只修了大约一个星期,我觉得我可能会遗漏一些东西,以使这更容易/更快。

有这样的事吗?或者我是否可以手动迭代?

我有点希望像

这样的东西
lastSuccessfulRev = action.match("lastBuildRevision/SHA1")

3 个答案:

答案 0 :(得分:4)

使用Enumerable#find

actions = [
  {'dummy' => true },
  {'dummy' => true },
  {'dummy' => true },
  {'lastBuiltRevision' => { "SHA1" => "123abc" }},
  {'dummy' => true },
]
actions.find { |h|
  h.has_key? 'lastBuiltRevision'
}['lastBuiltRevision']['SHA1']
# => "123abc"

更新

如果没有匹配的项目,上面的代码会抛出NoMethodError。如果您不想获得例外,请使用以下代码。

rev = actions.find { |h| h.has_key? 'lastBuiltRevision' }
rev = rev['lastBuiltRevision']['SHA1'] if rev

答案 1 :(得分:2)

这是另一种方法,利用Enumerable#find的形式,它接受一个被调用的参数ifnone,并返回其返回值,如果find的块从不评估true

我假设如果找不到任何一个密钥,该方法将返回nil

<强>代码

def look_for(actions, k1, k2)
  actions.find(->{{k1=>{}}}) { |e| e.key?(k1) }[k1][k2]
end

<强>实施例

actions = [{ 'dog'=>'woof' }, { 'lastBuiltRevision'=>{ 'SHA1'=> 2 } }]

look_for(actions, 'lastBuiltRevision', 'SHA1') #=> 2
look_for(actions, 'cat, 'SHA1')                #=> nil
look_for(actions, 'lastBuiltRevision', 'cat')  #=> nil

<强>解释

我已将find的{​​{1}}参数设为lambda:

ifnone

这样:

l = ->{{k1=>{}}}

答案 2 :(得分:1)

尝试:

action.map { |a| a["lastBuiltRevision"] }.compact.map { |lb| lb["SHA1"] }.first