在嵌套散列中查找值
我正在尝试执行类似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。在这种情况下,我能够通过使用该名称拆分,以获得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"}
}
} }
现在我想找到的ID “theFoo” - 即键和名称值之间没有关联。
发现了一种嵌套的地图做,紧凑和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
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?
试试这个来找到你需要的'ID',
data.find{ |k,v| k == "typeA"}[1].find{ |k,v| k == "statX"}[1]
.find{ |k,v| k == "funcB"}[1]["id"]
==> 7
嗨Sravan,我不清楚我如何问我的问题 - 我想找到一种方式来获得ID而不指定任何密钥的哈希,即使用map/find。我添加了一个使用散列的新例子。寻找一种单行的方式来找到它,而不是嵌套的'.each'循环。 – Brett
1.你的意思是你想找到“typeA_funcB_statX”的ID(即是一个错字? )?如果“typeA_funcB_stat”确实是你的意思,请解释匹配标准。 2.'data'包含两个你应该修复的错误:a)按照写法,'name'必须是局部变量或方法。如果你的意思是一个文字,把它改为'“name”'或':name'。 b)在最后你错过了一个右括号('}')。一定要检查输入是否正确。正确的格式化有助于获得匹配的'()','[]'和{}'对。 –
对不起,是的 - 一个错字 - 'statX' – Brett
你仍然需要编辑来处理我的第二点。 –