python - 如何使用 CommentedMap 对 YAML 进行递归排序?

标签 python python-3.x yaml ruamel.yaml

a good example在顶层排序,但是如何在所有级别递归排序?

这似乎有效:

   def sort_commentedmap(self, od):
       res = ruamel.yaml.comments.CommentedMap()
       for k in sorted(od):
           res[k] = od[k]
           if not isinstance(od[k], ruamel.yaml.comments.CommentedSeq):
               continue
           for idx, i in enumerate(od[k]):
               if isinstance(i, str):
                   res[k][int(idx)] = i
               else:
                   res[k][int(idx)] = self.sort_commentedmap(i)
       return res

这看起来正确吗?

最佳答案

在 YAML 中,您可以将序列嵌套在映射中,并将映射嵌套在序列中。您也可以拥有标量节点,但它们不能嵌套任何内容。

因此,您需要一个处理这三个元素的函数,而不对标量执行任何操作。如果映射嵌套在序列的元素之一下,它应该递归访问序列的元素。当您有映射时,两者都会递归到值(下面可能有其他一些映射),并按键对映射本身进行排序。

在下面我使用 .insert 来保留行尾注释,如果您创建一个新的 CommentedMap,这会变得更加困难。这是因为 .pop() 不会删除与键关联的行尾注释,并且重新插入键将使注释重新关联。

运行:

import sys
import ruamel.yaml

yaml_str = """\
f: 3
e: 
- 10     # sequences can have nodes that are mappings
- 11
- x: A
  y: 30
  z: 
    m: 51  # this should be last
    l: 50
    k: 49  # this should be first 
d: 1
"""

def recursive_sort_mappings(s):
    if isinstance(s, list):
        for elem in s:
            recursive_sort_mappings(elem)
        return 
    if not isinstance(s, dict):
        return
    for key in sorted(s, reverse=True):
        value = s.pop(key)
        recursive_sort_mappings(value)
        s.insert(0, key, value)


yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
recursive_sort_mappings(data)
yaml.dump(data, sys.stdout)

给出:

d: 1
e:
- 10     # sequences can have nodes that are mappings
- 11
- x: A
  y: 30
  z:
    k: 49  # this should be first 
    l: 50
    m: 51  # this should be last
f: 3

(Python 2.7/3.4/3.5/3.6/3.7,ruamel.yaml 0.15.44)

关于python - 如何使用 CommentedMap 对 YAML 进行递归排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51386822/

相关文章:

python - Numpy 向量化弄乱了数据类型

python - 您可以更改 Tornado 应用程序的日志输出格式吗?

python - 使用 python 从终端读取字符串

json - 从 Swagger 文档生成 Yaml 或 Json 文件

amazon-web-services - 模板格式错误: YAML not well-formed in metric filters

php - 每个 Behat 上下文的不同环境 (Symfony 4.x)

javascript - 将所有下拉数据从 HTML/Jenja 发送回 Flask 服务器

python - 将输出转换为 numpy 数组

python-3.x - 为什么我的程序停止响应并崩溃?

python - 如何在 VSCode 中运行 python3 代码?/bin/sh : 1: python: not found