转储类似HAM的YAML键名

时间:2012-12-01 20:27:02

标签: ruby hash

获取以点分隔的所有Hash键(带嵌套)列表的简便方法是什么?

鉴于我有一个哈希:

{ level1: { level21: { level31: 'val1', 
                       level32: 'val2' }, 
            level22: 'val3' } 
}

所需的输出(字符串数组),表示散列中的所有键路径:

level1.level21.level31
level1.level21.level32
level1.level22

我目前的解决方案:

class HashKeysDumper
  def self.dump(hash)
    hash.map do |k, v|
      if v.is_a? Hash
        keys = dump(v)
        keys.map { |k1| [k, k1].join('.') }
      else
        k.to_s
      end
    end.flatten
  end
end

它也可以gist(带规格)。

3 个答案:

答案 0 :(得分:1)

嗯,这取决于您对清洁工的意思,但这里是较小的版本......

  1. 将在子类Hashes或Hash-alikes上工作
  2. 扩展哈希,使代码中的外观更清晰。

    class Hash
      def keydump
        map{|k,v|v.keydump.map{|a|"#{k}.#{a}"} rescue k.to_s}.flatten
      end
    end
    
  3. 结果:

    { level1: { level21: { level31: 'val1', 
                           level32: 'val2' }, 
                level22: 'val3' } 
    }.keydump
    => ["level1.level21.level31", "level1.level21.level32", "level1.level22"]
    

答案 1 :(得分:0)

以下是我对此的看法:

h = { 'level1' => { 'level2' => { 'level31' => 'val1', 'level32' => 'val2' } } }

class Hash
  def nested_keys
    self.inject([]) { |f, (k,v)| f += [k, v.is_a?(Hash) ? v.nested_keys : []] }.flatten
  end
end

keys = h.nested_keys

p keys
#=> ["level1", "level2", "level31", "level32"]

k1, k2 = keys.shift, keys.shift

puts [k1, k2, keys.shift].join('.')
#=> level1.level2.level31

puts [k1, k2, keys.shift].join('.')
#=> level1.level2.level32

Here is a Working Demo

答案 2 :(得分:0)

我刚刚向RubyTree提交了一些代码,其中添加了from_hash(),可以让您执行此操作:

require 'rubytree'

Tree::TreeNode.from_hash(hash).each_leaf.map{|n| "#{n.name}.#{n.parentage.map(&:name).reverse.join('.')}" }

=> ["level1.level21.level31", "level1.level21.level32", "level1.level22"]

除了宝石要求之外,它还是一个单线:)