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 - Fatal编程技术网

如何在ruby中获取复杂嵌套哈希的元素?

如何在ruby中获取复杂嵌套哈希的元素?,ruby,Ruby,我在Ruby程序中有以下嵌套哈希。如何为循环编写一个,最终打印出每个数组中包含的元素 alternatives = { "JAVA" => { "/usr/bin" => [ "java", "keytool", "orbd", "pack200", "rmid", "rmiregistry", "servertool", "tnameserv", "unpack200" ], "/usr/lib" => [ "j

我在Ruby程序中有以下嵌套哈希。如何为循环编写一个
,最终打印出每个数组中包含的元素

alternatives = {
  "JAVA" => {
    "/usr/bin" => [
      "java", "keytool", "orbd", "pack200", "rmid",
      "rmiregistry", "servertool", "tnameserv", "unpack200"
    ],
    "/usr/lib" => [
      "jre", "jre_exports" 
    ],
    "/usr/share" => [
      "java.1", "keytool.1", "orbd.1", "pack200.1", "rmid.1",
      "rmiregistry.1", "servertool.1", "tnameserv.1", "unpack200.1"
    ]
  },
  "JDK" => {
    "/usr/bin" => [
      "javac", "appletviewer", "apt", 
      "extcheck", "jar", "jarsigner", "javadoc", "javah", "javap", 
      "jconsole", "jdb", "jhat", "jinfo", "jmap", "jps", 
      "jrunscript", "jstack", "jstat", "jstatd", "native2ascii",
      "policytool", "rmic", "schemagen", "servialver", "wsgen",
      "wsimport", "xjc" 
    ],
    "/usr/lib" => [
      "java_sdk", "java_sdk_exports"
    ],
    "/usr/share/man/man1" => [
      "javac.1", "appletviewer.1", "apt.1", 
      "extcheck.1", "jar.1", "jarsigner.1", "javadoc.1", "javah.1",
      "javap.1", "jconsole.1", "jdb.1", "jhat.1", "jinfo.1", "jmap.1",
      "jps.1", "jrunscript.1", "jstack.1", "jstat.1", "jstatd.1",
      "native2ascii.1", "policytool.1", "rmic.1", "schemagen.1",
      "servialver.1", "wsgen.1", "wsimport.1", "xjc" 
    ]
  }
}
这是我要做的伪代码

alternatives.each do |first_level_keys| # Gets the JAVA, JDK keys
  first_level_keys.each do |second_level_keys| # Gets the /usr/... keys
    second_level_keys.each do |array|
      array.each do |elem|
        puts "elem: " + elem
      end
    end
  end
end

我看到了“”,但似乎没有什么意义。

我想这就是您所需要的:

alternatives.each_value {|h| h.each_value {|a| a.each {|e| puts "elem: #{e}"}}}
elem: java
elem: keytool
elem: orbd
elem: pack200
...
elem: wsgen.1
elem: wsimport.1
elem: xjc
如果对象具有嵌套数组和散列,且嵌套级别不同,则可以按如下方式打印所有本身不是数组或散列的值。对于散列中的
键值
对,如果不是数组或散列,将打印

def print_innermost(o)
  case o
  when Hash then  o.each { |_,v| print_innermost(v) }
  when Array then o.each { |e|   print_innermost(e) }
  else puts "elem: #{o}"
  end
end

print_innermost(alternatives)
elem: java
elem: keytool
elem: orbd
elem: pack200
...
elem: wsgen.1
elem: wsimport.1
elem: xjc

alternatives = [{a: {b: {c: [1,2], d: {e: [3,4], f: 5}}}}, [{g: [6,7]}], 8]

print_innermost(alternatives)
elem: 1
elem: 2
elem: 3
elem: 4
elem: 5
elem: 6
elem: 7
elem: 8
“”解决了一个类似的问题,但有一个很大的区别:在这个例子中,OP知道他在寻找什么键。在你的情况下,在我看来,你只是试图访问列表中的所有值,因此其他问题中提交的答案并不完全适用

如果您试图做的只是访问数组中的元素,那么您可以用不同的方式进行访问。我的特殊方法不是在
for
循环中(Ruby中甚至没有使用
for
循环,更多信息请参见“”),而是使用递归方法。创建一个接受参数的函数。如果它是一个数组,它将打印元素,否则我们假设它是一个散列,并且在每个
值上调用该函数(我们只是忽略键)

守则是:

def get_elements(obj)
  if obj.is_a?(Array)
    obj.each {|element| puts "elem:" + element }
  else
    obj.each {|key, value| get_elements(value) }
  end
end

get_elements(alternatives)
或者,如果您理解,您可以
生成
元素,这样您就可以在代码的另一部分中对它们执行任何操作

def get_elements(obj)
  if obj.is_a?(Array)
    obj.each {|element| yield element }
  else
    obj.each {|key, value| get_elements(value) }
  end
end

get_elements(alternatives) {|elem| puts "elem:" + elem }

您不需要获取第一级哈希的键,然后使用这些键来获取值——因为您可以直接获取值:

alternatives.values.each do |hash| # Gets the values for JAVA, JDK keys
  hash.values.each do |arr| # Gets the values for the /usr/... keys
    arr.each do |elmt|
      puts "elem: " + elmt
    end
  end
end
如果您的散列有不同级别的嵌套,那么递归就是答案,尽管递归很难学习

警告!递归前进

def get_arrays(hash)
  results = []

  hash.values.each do |value|
    case value
      when Hash
        get_arrays(value).each do |elmt|
          results << elmt
        end
      when Array
        results << value
    end

  end

  results
end


h = {
  a: [1, 2],
  b: 100,
  c: {
       d: [3, 4, 5],
       e: { f: [6, 7] }
     },
  j: { 
       k: [8, 9], 
       l: [10, 11, 12]
     },
}



results = get_arrays(h)
p results

results.each do |arr|
  arr.each do |elmt|
    print "#{elmt} "
  end
  puts 
end


--output:--
[[1, 2], [3, 4, 5], [6, 7], [8, 9], [10, 11, 12]]
1 2 
3 4 5 
6 7 
8 9 
10 11 12 
def get_数组(散列)
结果=[]
hash.values.each do|值|
案例价值
当散列
获取|数组(值)。每个都做| elmt|

结果我知道您要求使用基于循环的解决方案,但是如果您愿意使用标准库中的哈希和数组方法,就没有必要了

我会这样做:

alternatives.values.collect(&:values).flatten
说明:

  • .values
    删除键,为您提供一个哈希数组:
    [{'usr/bin'=>[…],'usr/lib'=>[…]},…]
  • .collect(&:values)
    获取该散列数组并再次删除键,从而为您提供一个字符串数组数组,如下所示:
    [[“java”,…],[jre,…],…]
  • .flant
    将数组转换为一维字符串数组
我会添加
uniq.sort
用于删除任何重复项并按字母顺序对结果排序,除非您需要重复项(然后删除
uniq


我用了一个修改过的7stud的答案

因为我还需要键的值(例如,JAVA、JDK、/usr/…),所以我结束了这项工作:

alternatives.keys.each do |alt_keys| # Gets the values for JAVA, JDK keys
  alternatives[alt_keys].each do |arr| # Gets the values for the /usr/... keys
    puts "array key: " + arr.to_s
    alternatives[alt_keys][arr].each do |elmt|
      puts "elem: " + elmt
    end
  end
end

多亏了大家,我以后也会尝试其他答案。

不要说“例如,这个”,而是在锚文本中加入更明确的内容,让人们了解他们将要做什么。请参见“和”。不要说“链接”或“这篇文章”,在锚文本中加入一些更明确的内容,让人们了解他们将要做什么。请参见“”和“”。在您看来,collect()不是一个循环?Flatte()如何?我的意思是一个
for
循环。好吧,为什么不将文本改为“for”循环。因为我认为这已经足够清楚了。特别是现在我们有了这些注释。
alternatives.keys.each do |alt_keys| # Gets the values for JAVA, JDK keys
  alternatives[alt_keys].each do |arr| # Gets the values for the /usr/... keys
    puts "array key: " + arr.to_s
    alternatives[alt_keys][arr].each do |elmt|
      puts "elem: " + elmt
    end
  end
end