Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 访问嵌套散列中的值_Ruby_Hash - Fatal编程技术网

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)