如何使用 CommentedMap 对 YAML 进行递归排序? [英] How to recursively sort YAML using CommentedMap?

查看:38
本文介绍了如何使用 CommentedMap 对 YAML 进行递归排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个很好的例子是在顶层进行排序,但是您将如何在所有级别递归排序?

There's a good example of sorting at the top level, but how would you recurse the sort at all levels?

这似乎有效:

   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 中,您可以将序列嵌套在映射中,并将映射嵌套在序列中.你也可以有标量节点,但那些不能嵌套任何东西.

In YAML you can have sequences nested in mappings and mappings nested in sequences. You can also have scalar nodes, but those cannot nest anything.

所以你需要一个处理这三个元素的函数,对标量不做任何事情.如果映射嵌套在其元素之一下,它应该递归访问序列的元素.当你有一个映射时,两者都递归到值中(下面可能有其他一些映射),并按键对映射本身进行排序.

So you need a function that processes the three elements, doing nothing on scalars. It should recursively access the elements of a sequence in case a mapping is nested under one of its elements. And when you have a mapping, both recurse into the values (which might have some other mapping down below), and sort the mapping itself by key.

在下面我使用 .insert 来保留行尾注释,如果你创建一个新的 CommentedMap,这会更困难.之所以有效,是因为 .pop() 不会删除与键关联的行尾注释,重新插入键将使注释重新关联.

In the following I use .insert which preserves end-of-line comments, something that would be more difficult if you created a new CommentedMap. That this works is because .pop() doesn't delete an end-of-line comment associated with a key, and reinstering the key will get the comment re-associated.

运行:

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 2.7/3.4/3.5/3.6/3.7, ruamel.yaml 0.15.44)

这篇关于如何使用 CommentedMap 对 YAML 进行递归排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆