【问题标题】:Dump YAML-like key names of Hash转储类似 YAML 的 Hash 键名
【发布时间】:2012-12-05 09:27:20
【问题描述】:

获取由点分隔的所有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(带有规格)。

【问题讨论】:

  • 请不要链接到您的代码,而是将它的摘要版本添加到您的问题中,格式正确,这样我们就可以快速访问它,而不必追逐它。这有助于我们帮助您,也有助于保持您的问题的相关性。如果该链接失效,您的问题将无法供日后寻找类似问题答案的人使用。
  • 实际上,您的解决方案对我来说看起来不错。你有什么特别想改变的吗? (我同意@theTinMan 的观点,您应该将其添加到您的问题中)。
  • @theTinMan 感谢我编辑问题的提示
  • @MarkThomas 我实际上对我的解决方案很满意,但很好奇是否可以更清洁地完成这项工作

标签: ruby hash


【解决方案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
    

结果:

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

【讨论】:

  • 感谢@Mark,但我实际上不喜欢猴子补丁核心类(至少除非 Ruby 2.0 有改进)。因此,恕我直言,将所有内容保存在单独的类/模块中更干净。
  • 我喜欢你的解决方案马克,漂亮而优雅。谢谢!
【解决方案2】:

这是我的看法:

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

【讨论】:

  • @Andrey,请查看更新的答案。第一个版本有点匆忙... :) 对你有帮助吗?
  • 感谢@slivu,但我不确定这是否真的适用于像这样的更复杂的哈希 { level1: { level21: 'val', level22: { level31: 'value1', level32: '值2' } } }
  • 它确实将哈希的所有键作为数组返回。 hash 可以是任何嵌套级别。这不是你在问题中问的吗?
  • 我想要的是获取所有关键路径。我已经用更好的描述更新了我的问题。
【解决方案3】:

我刚刚向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 要求之外,它是单行的 :)

【讨论】:

    猜你喜欢
    • 2013-08-13
    • 2019-09-03
    • 1970-01-01
    • 2021-02-19
    • 2011-11-30
    • 2013-03-25
    • 1970-01-01
    相关资源
    最近更新 更多