2

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(带有规格)。

4

3 回答 3

1

好吧,这取决于您所说的清洁剂是什么意思,但这里有一个较小的版本……

  1. 将适用于子类 Hashes 或 Hash-alikes
  2. 扩展 Hash,使其在您的代码中看起来更清晰。

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

结果:

{ level1: { level21: { level31: 'val1', 
                       level32: 'val2' }, 
            level22: 'val3' } 
}.keydump
=> ["level1.level21.level31", "level1.level21.level32", "level1.level22"]
于 2012-12-03T00:03:01.353 回答
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"]

除了 gem 要求之外,它是一个单线 :)

于 2012-12-05T01:27:20.913 回答
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

这是一个工作演示

于 2012-12-01T20:48:34.860 回答