嵌套散列值访问值
我试图过滤嵌套散列并拉出各种键和值。下面是我在看的哈希:嵌套散列值访问值
exp = {
fam: {cty: "bk", ins: 3},
spec: {cty: "man", ins: 2},
br: {cty: "qns", ins: 1},
aha: {cty: "man", ins: 0}
}
我试图找到所有的哈希键,其中cty
是"man"
。我想运行的东西,结果就是下面的哈希:
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}
}
首先,您需要了解迭代一个哈希会给你。
考虑一下:
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}]]
注意,零值都没有了。
重写你的代码考虑到这一点,再加上重构它简单:
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
现在它回到你想要的钥匙,所以就很容易抓住整个哈希。 select
是当你试图找到具体的事情要使用适当的方法:红宝石的
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}}
旧版本并没有维持从哈希散列迭代器输出,所以我们不得不强制回哈希表:
e = exp.select { |k, v| v[:cty] == 'man' }.to_h
# => {:spec=>{:cty=>"man", :ins=>2}, :aha=>{:cty=>"man", :ins=>0}}
e = {}
exp.each do |k,v|
if v[:cty] == "man"
e[k] = v
end
end
p e
甚至
e = exp.select do |k,v|
v[:cty] == "man"
end
作为锡文指出的那样,有两个参数可在通过散列迭代时传递到块(在这种情况下do
和end
之间的代码)---一个用于其键和其他的价值。 要迭代虽然哈希(并打印出其值)使用.each
方法
h = { a: "hello", b: "bonjour", c: "hola" }
,你可以这样做:
h.each do |key, value|
puts value
end
结果将是:
hello
bonjour
hola
=> {:a=>"hello", :b=>"bonjour", :c=>"hola"}
请注意,值“返回”是我们迭代的散列值,其值在红宝石中为true
。 (以外的任何其他nil
或false
将评估在红宝石true
见What evaluates to false in Ruby?)
这是重要的,因为你在你的代码了true
(这其实应该是{:fam=>{:cty=>"bk", :ins=>3}, :spec=>{:cty=>"man", :ins=>2}, :br=>{:cty=>"qns", :ins=>1}, :aha=>{:cty=>"man", :ins=>0}}
)的原因,而不是你想要的解析的哈希对于散列而言,由.each
方法返回的值是散列本身(其评估为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
将被分配原始散列exp
本身,这是不是我们想要的。因此,理解应用方法时返回值的含义非常重要。
有关返回值(以及一般Ruby)的更多信息,我强烈推荐LaunchSchool的免费电子书“用Ruby编程简介”(https://launchschool.com/books/ruby)。这不仅帮助我认识到返回值的重要性,而且为我提供了一个通用的Ruby prigramming的坚实基础,如果您打算学习Ruby on Rails(我现在正在这么做:)),这非常有用。
简单到深入挖掘嵌套哈希方法是: -
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)
欢迎SO。我们不在乎你的经验水平是什么,只是向我们展示你的研究成果,并且已经为解决问题付出了很大的努力,然后写出一个很好的问题。请不要使用称呼,说话或签名; SO不是论坛,它是一个问题和答案的参考书。 –