Sort Dictionary of Dictionaries on multiple child dictionary values

社会主义新天地 提交于 2020-01-11 04:10:07

问题


I have a dictionary that looks like this:

myDict = {
    'SER12346': {'serial_num': 'SER12346', 'site_location': 'North America'},
    'ABC12345': {'serial_num': 'ABC12345', 'site_location': 'South America'},
    'SER12345': {'serial_num': 'SER12345', 'site_location': 'North America'},
    'SER12347': {'serial_num': 'SER12347', 'site_location': 'South America'},
    'ABC12346': {'serial_num': 'ABC12346', 'site_location': 'Europe'}
}

My goal is to sort this dictionary by the site_location and the serial_num of each of the child dictionaries.

Using code I found in this question - Sort a dictionary of dictionaries python - I was able to get it sorted, but it's not quite what I am expecting.

This is my code:

import pprint
items = ((k, k2, v) for k in myDict for k2, v in myDict[k].items())
ordered = sorted(items, key=lambda x:x[-1], reverse=False)
pprint.pprint(ordered)

This is the result I get:

[('ABC12346', 'site_location', 'Europe'),
 ('SER12345', 'site_location', 'North America'),
 ('SER12346', 'site_location', 'North America'),
 ('SER12347', 'site_location', 'South America'),
 ('ABC12345', 'site_location', 'South America'),
 ('ABC12346', 'serial_num': 'ABC12346'),
 ('SER12345', 'serial_num': 'SER12345'),
 ('SER12346', 'serial_num': 'SER12346'),
 ('SER12347', 'serial_num': 'SER12347'),
 ('ABC12345', 'serial_num': 'ABC12345')]

I was expecting something more like this though:

{
    'ABC12346': {'serial_num': 'ABC12346', 'site_location': 'Europe'}
    'SER12345': {'serial_num': 'SER12345', 'site_location': 'North America'},
    'SER12346': {'serial_num': 'SER12346', 'site_location': 'North America'},
    'SER12347': {'serial_num': 'SER12347', 'site_location': 'South America'},
    'ABC12345': {'serial_num': 'ABC12345', 'site_location': 'South America'},
}

The actual result is separating the serial number and site location. I want to keep them together in the sorted object. How can I do this?


回答1:


Is this what you wanted?

dicts = [{k: v} for (k,v) in myDict.items()]
dicts.sort(key=lambda d: (d.values()[0]['site_location'], d.values()[0]['serial_num'],))

Output for doing:

import pprint
pprint.pprint(dicts)

is:

[{'ABC12346': {'serial_num': 'ABC12346', 'site_location': 'Europe'}},
 {'SER12345': {'serial_num': 'SER12345', 'site_location': 'North America'}},
 {'SER12346': {'serial_num': 'SER12346', 'site_location': 'North America'}},
 {'ABC12345': {'serial_num': 'ABC12345', 'site_location': 'South America'}},
 {'SER12347': {'serial_num': 'SER12347', 'site_location': 'South America'}}]

EDIT: I was going on your answer for the output format, but this would probably make more sense:

dicts = myDict.items()
dicts.sort(key=lambda (k,d): (d['site_location'], d['serial_num'],))

Output:

[('ABC12346', {'serial_num': 'ABC12346', 'site_location': 'Europe'}),
 ('SER12345', {'serial_num': 'SER12345', 'site_location': 'North America'}),
 ('SER12346', {'serial_num': 'SER12346', 'site_location': 'North America'}),
 ('ABC12345', {'serial_num': 'ABC12345', 'site_location': 'South America'}),
 ('SER12347', {'serial_num': 'SER12347', 'site_location': 'South America'})]



回答2:


Dictionaries do not preserve order of items - hence can not be sorted. If you want an appearance of sorted dictionary, you need to make a sorted list and then insert it into OrderedDict class. Code snippet below illustrates this:

from collections import OrderedDict

myDict = {
    'SER12346': {'serial_num': 'SER12346', 'site_location': 'North America'},
    'ABC12345': {'serial_num': 'ABC12345', 'site_location': 'South America'},
    'SER12345': {'serial_num': 'SER12345', 'site_location': 'North America'},
    'SER12347': {'serial_num': 'SER12347', 'site_location': 'South America'},
    'ABC12346': {'serial_num': 'ABC12346', 'site_location': 'Europe'}
}

def sortfun(d):
    return (d[1]['site_location'], d[1]['serial_num'])

skv = sorted(myDict.iteritems(), key=sortfun)
sorted_dict = OrderedDict(skv)

print sorted_dict



回答3:


>>> import pprint
>>> dic=myDict.items()
>>> dic.sort(key=lambda x:(x[1]['site_location'],x[1]['serial_num']))
>>> pprint.pprint([{k:v} for k,v in dic])
[{'ABC12346': {'serial_num': 'ABC12346', 'site_location': 'Europe'}},
 {'SER12345': {'serial_num': 'SER12345', 'site_location': 'North America'}},
 {'SER12346': {'serial_num': 'SER12346', 'site_location': 'North America'}},
 {'ABC12345': {'serial_num': 'ABC12345', 'site_location': 'South America'}},
 {'SER12347': {'serial_num': 'SER12347', 'site_location': 'South America'}}]



回答4:


I have a solution with cmp (I think you must use that since we use a mix of 2 keys) but it's not really pretty, I guess it can be improved:

>>> pprint(sorted(myDict.items(), cmp=lambda x, y: cmp((x[1]['site_location'], x[1]['serial_num']), (y[1]['site_location'], y[1]['serial_num']))))
[('ABC12346', {'serial_num': 'ABC12346', 'site_location': 'Europe'}),
 ('SER12345', {'serial_num': 'SER12345', 'site_location': 'North America'}),
 ('SER12346', {'serial_num': 'SER12346', 'site_location': 'North America'}),
 ('ABC12345', {'serial_num': 'ABC12345', 'site_location': 'South America'}),
 ('SER12347', {'serial_num': 'SER12347', 'site_location': 'South America'})]


来源:https://stackoverflow.com/questions/11346111/sort-dictionary-of-dictionaries-on-multiple-child-dictionary-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!