2

I want to sort all lists within a deeply nested dictionary. It is basically a JSON object which deep nesting of dictionaries within lists and then lists within dictionaries. All I want to do is, parse through all dictionary keys to all leaf nodes and sort all the lists that i encounter on the way. Basically, any list directly available or deep down within that given dictionary object should get sorted and the same dictionary with all sorted lists should be returned.

I tried doing recursion on the dict object to pass any dict object encountered to the recursion method and sorting the lists when encountered. But they fail to produce results when there is a dict inside a list and then another list inside that dict object.

Sample JSON below:

my_json = {
  a: {
    b: {
      c: [
        {
          d: [
            { f: 'some_string' }
          ]
        },
        {
          e: {
            g: [
              h: 'another string'
            ]
          }
        }
      ]
    }
  }
  z: [
    b: {
      c: [
        {
          d: [
            { f: 'some_string1' }
          ]
        },
        {
          e: {
            g: [
              h: 'another string1'
            ]
          }
        }
      ]
    },
    x: {
      c: [
        {
          d: [
            { f: 'some_string2' }
          ]
        },
        {
          e: {
            g: [
              h: 'another string2'
            ]
          }
        }
      ]
    }
  ]
}
def gen_dict_extract(input_dict):
  result_obj = input_dict;
  if hasattr(var, 'iteritems'):
    for k, v in var.iteritems():
      if isinstance(v, dict):
        for result in gen_dict_extract(v):
          yield result
      elif isinstance(v, list):
        v.sort();
        for d in v:
          for result in gen_dict_extract(d):
            yield result

The output expectation is just to have all lists sorted irrespective of where they lie. I am even okay with sorting every item in the dictionary but list sorting is what I require.

Taking a smaller example here to explain the output:

old_json = {
    'x': [
        {
            'z': {
                'y': ['agsd', 'xef', 'sdsd', 'erer']
            }
        },
        {
            's': {
                'f': 'ererer',
                'd': [5, 6, 2, 3, 1]
            }
        }
    ]
}

new_json = {
    'x': [
        {
            's': {
                'f': 'ererer',
                'd': [1, 2, 3, 5, 6]
            }
        },
        {
            'z': {
                'y': ['agsd', 'erer', 'sdsd','xef']
            }
        }
    ]
}

Something like above.
8
  • 1
    Please give a minimal reproducible example to illustrate what you've tried and the specific problem with it. Commented May 25, 2019 at 12:56
  • I know you've tried really hard to explain the output you're looking for but I still don't get it. Can you update your post include what the sample JSON would get converted to explicitly? In the question please! Commented May 25, 2019 at 12:58
  • Please add your expected output in question. That will help us to solve your issue easily. Commented May 25, 2019 at 13:09
  • Done.. Please take a look. Please ignore my code as it might not serve the exact purpose i am looking for. Commented May 25, 2019 at 13:11
  • Please revisit your input data. Looks like there are some syntax errors Commented May 25, 2019 at 13:34

2 Answers 2

2

If you want the output to be a different dictionary (i.e. not sorting the original), the function should be written like this:

def sortedDeep(d):
    if isinstance(d,list):
        return sorted( sortedDeep(v) for v in d )
    if isinstance(d,dict):
        return { k: sortedDeep(d[k]) for k in sorted(d)}
    return d

This way you can use sortedDeep() the same way you would use the buil-in sorted() function:

new_json = sortedDeep(old_json)

[EDIT] Improved version that will also sort lists of dictionaries (or list of lists) based on the smallest key/value of the embedded object:

def sortedDeep(d):
    def makeTuple(v): return (*v,) if isinstance(v,(list,dict)) else (v,)
    if isinstance(d,list):
        return sorted( map(sortedDeep,d) ,key=makeTuple )
    if isinstance(d,dict):
        return { k: sortedDeep(d[k]) for k in sorted(d)}
    return d
Sign up to request clarification or add additional context in comments.

10 Comments

This will work for a dict without duplicate keys. How about when we have to sort a dict with duplicate keys?
Not sure what you mean by a dictionary with duplicate keys. By definition the keys in a dictionary are unique.
Sorry, I meant JSON. How to deep sort when JSON has duplicate keys? And it can be a list of json of list and so on.
I don't think JSON supports duplicate keys in a dictionary either. But, if your question pertains to a 'list of dictionaries' (or list of objects in JSON vernacular), then it won't work as is. I added an improved version that will do it based on the smallest key of each dictionary in the list.
I have a payload something like this: ls = {'payload': [{'a': {'aa': [{'aa12': {'aaa23': 230, 'aaa21': 210}}, {'aa11': {'aaa12': 120, 'aaa11': 110}}, {'aa13': {'aaa35': 350, 'aaa32': 320}}], 'ac': ['ac3', 'ac1', 'ac2'], 'aa': [{'aa12': {'aaa22': 22, 'aaa21': 21}}, {'aa01': {'aaa03': 03, 'aaa01': 01}}, {'aa13': {'aaa33': 33, 'aaa32': 32}}, {'aa1': 'aab'}], 'ac': ['ac3', 'ac1', 'ac2']}}, {'b': {'bb': ['bb4', 'bb2', 'bb3', 'bb1']}}]}. How do I sort this? With the above code, it is still removing duplicate keys.
|
0

I believe the code snippet here will do the job for sorting nested dictionaries.

def nested_sort(d:dict):
    for v in d.values():
        if isinstance(v,dict):
            nested_sort(v)
        elif isinstance(v,list):
            v.sort()

However, I cannot test the code because the example you gave is not in legal JSON format or a legal python dictionary.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.