【问题标题】:In Ruby, how to be warned of duplicate keys in hashes when loading a YAML document?在 Ruby 中,如何在加载 YAML 文档时警告哈希中的重复键?
【发布时间】:2011-02-06 02:22:11
【问题描述】:

在以下 Ruby 示例中,是否有一种模式可以让 YAMLNOT 静默忽略重复键“one”?

irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> str = '{ one: 1, one: 2 }'
=> "{ one: 1, one: 2 }"
irb(main):003:0> YAML.load(str)
=> {"one"=>2}

谢谢!

【问题讨论】:

    标签: ruby yaml


    【解决方案1】:

    使用 Psych,您可以遍历 AST 树以查找重复键。我在我的测试套件中使用以下辅助方法来验证我的 i18n 翻译中没有重复的键:

    def duplicate_keys(file_or_content)
      yaml = file_or_content.is_a?(File) ? file_or_content.read : file_or_content
      duplicate_keys = []
    
      validator = ->(node, parent_path) do
        if node.is_a?(Psych::Nodes::Mapping)
          children = node.children.each_slice(2) # In a Mapping, every other child is the key node, the other is the value node.
          duplicates = children.map { |key_node, _value_node| key_node }.group_by(&:value).select { |_value, nodes| nodes.size > 1 }
    
          duplicates.each do |key, nodes|
            duplicate_key = {
              file: (file_or_content.path if file_or_content.is_a?(File)),
              key: parent_path + [key],
              occurrences: nodes.map { |occurrence| "line: #{occurrence.start_line + 1}" },
            }.compact
    
            duplicate_keys << duplicate_key
          end
    
          children.each { |key_node, value_node| validator.call(value_node, parent_path + [key_node.try(:value)].compact) }
        else
          node.children.to_a.each { |child| validator.call(child, parent_path) }
        end
      end
    
      ast = Psych.parse_stream(yaml)
      validator.call(ast, [])
    
      duplicate_keys
    end
    

    【讨论】:

    • 谢谢。这非常有用!
    【解决方案2】:

    有一个涉及 linter 的解决方案,但我不确定它是否与 因为它不是 100% 的 Ruby 解决方案。反正我会发,因为我不知道 在 Ruby 中执行此操作的任何方法:

    您可以使用yamllint 命令行工具:

    sudo pip install yamllint
    

    具体来说,它有一个规则key-duplicates 可以检测重复的键:

    $ cat test.yml
    { one: 1, one: 2 }
    
    $ yamllint test.yml
    test.yml
      1:11      error    duplication of key "one" in mapping  (key-duplicates)
    

    【讨论】:

      【解决方案3】:

      为了帮助维护我使用的 YAML 文件,我做的一件事是编写代码以最初从 Ruby 中的已知结构生成它。这让我开始了。

      然后,我将编写一个小 sn-p 来加载它并输出它使用 PrettyPrintAwesome Print 解析的内容,以便我可以将其与文件进行比较。

      我还会根据需要对字段进行排序,以便于查找重复项。

      【讨论】:

        【解决方案4】:

        没有。您必须决定如何重命名键,因为哈希键必须是唯一的 - 我会采取一些解决方法,例如手动查找相同的键并在执行 YAML::load 之前重命名它们。

        【讨论】:

          猜你喜欢
          • 2021-11-03
          • 1970-01-01
          • 2013-01-24
          • 2016-01-02
          • 2016-11-14
          • 2011-05-08
          • 1970-01-01
          • 2010-11-29
          • 2013-07-14
          相关资源
          最近更新 更多