Ruby:获取哈希中的所有键(包括子键)

use*_*703 18 ruby hash

让我们有这个哈希:

hash = {"a" => 1, "b" => {"c" => 3}}
hash.get_all_keys 
=> ["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)

我怎么能得到所有的钥匙,因为hash.keys返回["a", "b"]

Car*_*and 22

这将为您提供任何嵌套级别的所有键的数组.

def get_em(h)
  h.each_with_object([]) do |(k,v),keys|      
    keys << k
    keys.concat(get_em(v)) if v.is_a? Hash
  end
end

hash = {"a" => 1, "b" => {"c" => {"d" => 3}}}
get_em(hash) #  => ["a", "b", "c", "d"]
Run Code Online (Sandbox Code Playgroud)


hir*_*lau 5

我觉得grep这里有用:

def get_keys(hash)
  ( hash.keys + hash.values.grep(Hash){|sub_hash| get_keys(sub_hash) } ).flatten
end

p get_keys my_nested_hash #=> ["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)

我喜欢这个解决方案,因为它很短,但读起来非常好.


Dor*_*ian 5

保留密钥层次结构的版本

  • 适用于数组
  • 适用于嵌套哈希

keys_only.rb

# one-liner
def keys_only(h); h.map { |k, v| v = v.first if v.is_a?(Array); v.is_a?(Hash) ? [k, keys_only(v)] : k }; end

# nicer
def keys_only(h)
  h.map do |k, v|
    v = v.first if v.is_a?(Array);

    if v.is_a?(Hash)
      [k, keys_only(v)]
    else
      k
    end
  end
end

hash = { a: 1, b: { c: { d: 3 } }, e: [{ f: 3 }, { f: 5 }] }
keys_only(hash)
# => [:a, [:b, [[:c, [:d]]]], [:e, [:f]]]
Run Code Online (Sandbox Code Playgroud)

PS:是的,它看起来像一个词法分析器:D

奖励:在漂亮的嵌套列表中打印键

# one-liner
def print_keys(a, n = 0); a.each { |el| el.is_a?(Array) ? el[1] && el[1].class == Array ? print_keys(el, n) : print_keys(el, n + 1) : (puts "  " * n + "- #{el}") }; nil; end

# nicer
def print_keys(a, n = 0)
  a.each do |el|
    if el.is_a?(Array)
       if el[1] && el[1].class == Array
         print_keys(el, n)
       else
         print_keys(el, n + 1)
       end
    else
      puts "  " * n + "- #{el}"
    end
  end

  nil
end


> print_keys(keys_only(hash))
- a
  - b
      - c
        - d
  - e
    - f
Run Code Online (Sandbox Code Playgroud)