user1768233
user1768233

Reputation: 1461

How can I print a Python dictionary as YAML sorted by key depth

I have some code that generates a nested dictionary structure. I'm then printing it as YAML by doing the following:

print(yaml.dump(mydict, sort_keys=False))

the data structure looks something like the following

    "DeviceInfo": {
        "autoApply": 'true',
        "comment": "this is a test",
        "contact": {
            "email": "Hello",
            "name": "aaaaa",
            "phoneNumber": "(111) 111 111"
        },
        "location": {
            "address": "2100 Moorpark Ave",
            "city": "San Jose",
            "country": "US",
            "latitude": 36,
            "longitude": 119,
            "state": "California",
            "zipCode": 94088
        },
        "networkRole": "non-hub",
        "region": "North",
         "group": "Group 1",

    }}

and the resulting YAML:

DeviceInfo:
  autoApply: 'true'
  comment: this is a test
  contact:
    email: Hello
    name: aaaaa
    phoneNumber: (111) 111 111
  location:
    address: 2100 Moorpark Ave
    city: San Jose
    country: US
    latitude: 36
    longitude: 119
    state: California
    zipCode: 94088
  networkRole: non-hub
  region: North
  group: Group 1

what I would like to do is order the dictionary and therefore resulting YAML by key depth.

So have the output look like this.

DeviceInfo:
  autoApply: 'true'
  comment: this is a test
  networkRole: non-hub
  region: North
  group: Group 1  
  contact:
    email: Hello
    name: aaaaa
    phoneNumber: (111) 111 111
  location:
    address: 2100 Moorpark Ave
    city: San Jose
    country: US
    latitude: 36
    longitude: 119
    state: California
    zipCode: 94088

From testing yaml.dump ( with sort_keys=False ) seems to preserve the order of the dictionary. So what I am trying to accomplish is to sort the dictionary by ascending depth.

Upvotes: 1

Views: 291

Answers (1)

blhsing
blhsing

Reputation: 107015

You can use a recursive worker function that returns a tuple consisting of the depth of the current given dict and the dict sorted by depths of the keys. The base case of the recursion would be a depth of 0 when the given object is not a dict. The depth of the current dict is calculated as the maximum depth of all children plus 1:

def sort_dict_by_depth(d):
    def _sort_dict_by_depth(d):
        if isinstance(d, dict):
            children_depths = [(k, _sort_dict_by_depth(v)) for k, v in d.items()]
            return (
                max(depth for _, (depth, _) in children_depths) + 1,
                {k: v for k, (_, v) in sorted(children_depths, key=lambda t: t[1][0])}
            )
        return 0, d
    return _sort_dict_by_depth(d)[1]

Demo: https://replit.com/@blhsing/GrandBurlyDividend

Upvotes: 2

Related Questions