Ruby 访问嵌套散列中的值
我试图过滤嵌套哈希,并提取各种键和值。以下是我正在查看的哈希:Ruby 访问嵌套散列中的值,ruby,hash,Ruby,Hash,我试图过滤嵌套哈希,并提取各种键和值。以下是我正在查看的哈希: exp = { fam: {cty: "bk", ins: 3}, spec: {cty: "man", ins: 2}, br: {cty: "qns", ins: 1}, aha: {cty: "man", ins: 0} } 我正试图找到cty所在的所有散列键。我想运行结果为以下哈希的程序: e = { spec: {cty: "man", ins: 2}, aha: {cty: "man", ins: 0
exp = {
fam: {cty: "bk", ins: 3},
spec: {cty: "man", ins: 2},
br: {cty: "qns", ins: 1},
aha: {cty: "man", ins: 0}
}
我正试图找到cty所在的所有散列键。我想运行结果为以下哈希的程序:
e = {
spec: {cty: "man", ins: 2},
aha: {cty: "man", ins: 0}
}
我试过这个,它似乎几乎能起作用:
exp.each do |e, c, value|
c = :cty.to_s
value = "man"
if e[c] == value
puts e
end
end
但我得到的结果是:
=> true
而不是我想要的:
e = {
spec: {cty: "man", ins: 2},
aha: {cty: "man", ins: 0}
}
甚至
e = exp.select do |k,v|
v[:cty] == "man"
end
首先,您需要了解在散列上迭代会得到什么 考虑这一点:
exp = {
fam: {cty: "bk", ins: 3},
spec: {cty: "man", ins: 2},
br: {cty: "qns", ins: 1},
aha: {cty: "man", ins: 0}
}
exp.map { |e, c, value| [e, c, value] }
# => [[:fam, {:cty=>"bk", :ins=>3}, nil], [:spec, {:cty=>"man", :ins=>2}, nil], [:br, {:cty=>"qns", :ins=>1}, nil], [:aha, {:cty=>"man", :ins=>0}, nil]]
这基本上就是在循环时所做的,Ruby将块传递给键/值对。您告诉Ruby在e中给您当前的哈希键,在c中给您当前的哈希值,并且,因为没有传递任何其他内容,所以value参数变为nil
相反,键需要一个块变量,值需要一个块变量:
exp.map { |k, v| [k, v] }
# => [[:fam, {:cty=>"bk", :ins=>3}], [:spec, {:cty=>"man", :ins=>2}], [:br, {:cty=>"qns", :ins=>1}], [:aha, {:cty=>"man", :ins=>0}]]
请注意,nil值已消失
考虑到这一点,重新编写代码,并对其进行重构以简化:
exp = {
fam: {cty: 'bk', ins: 3},
spec: {cty: 'man', ins: 2},
br: {cty: 'qns', ins: 1},
aha: {cty: 'man', ins: 0}
}
exp.each do |k, v|
if v[:cty] == 'man'
puts k
end
end
# >> spec
# >> aha
现在它将返回您想要的密钥,因此抓取整个哈希变得很容易。当您试图定位特定对象时,是否使用合适的方法:
exp = {
fam: {cty: 'bk', ins: 3},
spec: {cty: 'man', ins: 2},
br: {cty: 'qns', ins: 1},
aha: {cty: 'man', ins: 0}
}
e = exp.select { |k, v| v[:cty] == 'man' }
# => {:spec=>{:cty=>"man", :ins=>2}, :aha=>{:cty=>"man", :ins=>0}}
Ruby的旧版本没有维护来自散列迭代器的散列输出,因此我们必须强制返回到散列:
e = exp.select { |k, v| v[:cty] == 'man' }.to_h
# => {:spec=>{:cty=>"man", :ins=>2}, :aha=>{:cty=>"man", :ins=>0}}
正如Tin Man所指出的,有两个参数可以传递到一个块中,在本例中,当迭代通过哈希时,代码位于do和end之间,一个用于其键,另一个用于其值。 迭代哈希并打印其值的步骤
h = { a: "hello", b: "bonjour", c: "hola" }
使用。每个方法,您都可以执行以下操作:
h.each do |key, value|
puts value
end
结果将是:
hello
bonjour
hola
=> {:a=>"hello", :b=>"bonjour", :c=>"hola"}
请注意,返回的值是我们迭代的哈希值,在ruby中计算结果为true。在Ruby中,除nil或false之外的任何值都将计算为true。看
这一点很重要,因为您在代码中得到true的原因实际上应该是{:fam=>{:cty=>bk,:ins=>3},:spec=>{:cty=>man,:ins=>2},:br=>{:cty=>qns,:ins=>1},:aha=>{:cty=>man,:ins=>0}},而不是您想要的解析哈希值。哈希的每个方法都是计算结果为true的哈希本身
这就是为什么osman创建了一个空的散列e={},这样在散列的每次迭代中,我们就可以用我们想要的键和值填充新创建的散列e
这就解释了他为什么能做到:
e = exp.select do |k,v|
v[:cty] == "man"
end
这里的代码取决于select方法是否能够返回一个新的散列,其中包含我们想要的键和值,而不是像.each方法那样返回原始散列
但如果你这样做了
e = exp.each do |k,v|
v[:cty] == "man"
end
变量e将被分配原始散列表达式本身,这不是我们想要的。因此,在应用方法时,理解返回值是什么是非常重要的
关于返回值和Ruby的更多信息,我强烈推荐LaunchSchool的免费电子书《Ruby编程入门》。这不仅帮助我认识到返回值的重要性,而且也给了我一个坚实的基础Ruby Primrima-一般来说,这是非常有用的,如果你正计划学习Ruby on Rails,我正在做:: < P>最简单的方式挖掘嵌套哈希是:-<
欢迎来到SO。我们不关心你的经验水平,只要向我们展示你的研究成果,以及你在解决问题上付出的努力,然后写一个好问题。请不要使用问候语、告别语或签名;因此,它不是一个讨论论坛,而是一本问答参考书。Ruby 2.3添加了一个方法,使之完全相同。
e = exp.each do |k,v|
v[:cty] == "man"
end
class Hash
def deep_find(key, object=self, found=nil)
if object.respond_to?(:key?) && object.key?(key)
return object[key]
elsif object.is_a? Enumerable
object.find { |*a| found = deep_find(key, a.last) }
return found
end
end
end
Hash.deep_find(key)