我正在尝试做类似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
行时,我可以使用select
或statData
方法,但想知道如何更有效/更有效地执行此操作。复杂性使我的地图调用无法解决。我怀疑一个好的解决方案是使用带有select / find调用的嵌套映射,也许是反转。
修改的
作为一个更好的示例,当我无法使用name
来确定任何密钥时,请考虑以下哈希:
data = {"typeA" => {
"statX" => {
"funcA" => {"id"=>1, "name"=>"theFoo"},
"funcB" => {"id"=>7, "name"=>"someBar"}
}
} }
现在我想找到“theFoo”的ID - 即键和名称值之间没有相关性。
答案 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