如何使用 CommentedMap 对 YAML 进行递归排序?
How to recursively sort YAML using CommentedMap?
顶层有 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)
顶层有 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)