在嵌套哈希中查找值

时间:2016-07-07 05:43:15

标签: ruby hash

我正在尝试做类似How to find a hash key containing a matching value的事情,但结构更复杂。使用嵌套的地图调用来解决这个问题是不成功的。

data = {"typeA" => {
  "statX" => {
     "funcA" => {"id"=>1, "name"=>"typeA_funcA_statX"},
     "funcB" => {"id"=>7, "name"=>"typeA_funcB_statX"}
  }
}}

现在我想找到“typeA_funcB_statX”的id。在这个例子中,我能够通过在名称上使用split来获取ID,并在传统的直接哈希引用中获取id:

type,func,stat = "typeA_funcB_statX".split("_")
id = data[type][stat][func]["id"]

如果名称是随机字符串,我可以通过编写嵌套的每个循环来查找ID(所有name个实例在散列中都是唯一的):

searchForName = "typeA_funcB_statX"
id = nil
data.each do |type,typeData|
  typeData.each do |stat,statData|
     statData.each do |func, funcData|
        id = funcData["id" if funcData["name"] == searchForName
     end
  end
end

当我到达find行时,我可以使用selectstatData方法,但想知道如何更有效/更有效地执行此操作。复杂性使我的地图调用无法解决。我怀疑一个好的解决方案是使用带有select / find调用的嵌套映射,也许是反转。

修改

作为一个更好的示例,当我无法使用name来确定任何密钥时,请考虑以下哈希:

data = {"typeA" => {
  "statX" => {
     "funcA" => {"id"=>1, "name"=>"theFoo"},
     "funcB" => {"id"=>7, "name"=>"someBar"}
  }
} }

现在我想找到“theFoo”的ID - 即键和名称值之间没有相关性。

3 个答案:

答案 0 :(得分:0)

data = {
  "typeA" => {
    "statX" => {
      "funcA" => {"id"=>1, :name=>"typeA_funcA_statX"},
      "funcB" => {"id"=>7, :name=>"typeA_funcB_statX"}
    }
  }
}

我认为这就是你要找的东西:

str = "typeA_funcB_statX"

data["typeA"]["statX"].values.find { |h| h[:name] == str }["id"]
  #=> 7

如果您不确定str"typeA_funcB_statX"此处)是否匹配,您可以写一下

val = data["typeA"]["statX"].values.find { |h| h[:name] == str }
val = val["id"] unless val.nil?

答案 1 :(得分:0)

尝试此操作以查找所需的“ID”,

data.find{ |k,v| k == "typeA"}[1].find{ |k,v| k == "statX"}[1]
.find{ |k,v| k == "funcB"}[1]["id"]

==> 7

答案 2 :(得分:0)

找到了一种方法,可以使用嵌套地图,紧凑和flatten.first:

fnd="theFoo"
data.map{|t,th|th.map{|s,sh|sh.map{|f,fh|fh["id"]if fh["name"]==fnd}.compact}}.flatten.first

==> 1