问题
There's a good example of sorting at the top level, but how would you recurse the sort at all levels?
This seems to work:
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
Does this look correct?
回答1:
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.
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.
Running:
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)
gives:
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)
来源:https://stackoverflow.com/questions/51386822/how-to-recursively-sort-yaml-using-commentedmap