简体   繁体   中英

How do I sort a key:list dictionary by values in list?

I have a dictionary

mydict = {'name':['peter', 'janice', 'andy'], 'age':[10, 30, 15]}

How do I sort this dictionary based on key=="name" list?

End result should be:

mydict = {'name':['andy', 'janice', 'peter'], 'age':[15, 30, 10]}

Or is dictionary the wrong approach for such data?

If you manipulate data, often it helps that each column be an observed variable (name, age), and each row be an observation (eg a sampled person). More on tidy data in this PDF link

Bad programmers worry about the code. Good programmers worry about data structures and their relationships - Linus Torvalds

A list of dictionaries lends itself better to operations like this. Below I present a beginner-friendly snippet to tidy your data. Once you have a good data structure, sorting by any variable is trivial even for a beginner. No one-liner Python kung-fu :)

>>> mydict = {'name':['peter', 'janice', 'andy'], 'age':[10, 30, 15]}

Let's work on a better data structure first

>>> persons = []
>>> for i, name in enumerate(mydict['name']):
...     persons.append({'name': name, 'age': mydict['age'][i]})
... 
>>> persons
[{'age': 10, 'name': 'peter'}, {'age': 30, 'name': 'janice'}, {'age': 15, 'name': 'andy'}]

Now it's easier to work on this data structure which is similar to "data frames" in data analysis environments. Let's sort it by person.name

>>> persons = sorted(persons, key=lambda person: person['name'])

Now bring it back to your format if you want to

>>> {'name': [p['name'] for p in persons], 'age': [p['age'] for p in persons]}
{'age': [15, 30, 10], 'name': ['andy', 'janice', 'peter']}

zip is used to make tuples (name, age)

dict = {'name':[], 'age':[]}
for name, age in sorted(zip(mydict['name'], mydict['age'])):
    dict['name'].append(name)
    dict['age'].append(age)

output:

{'age': [15, 30, 10], 'name': ['andy', 'janice', 'peter']}

A two-line version:

>>> s = sorted(zip(mydict['name'], mydict['age']))
>>> dict([('name', [x[0] for x in s]), ('age', [x[1] for x in s])])
{'age': [15, 30, 10], 'name': ['andy', 'janice', 'peter']}

You can use defaultdict ( for faster performance ) and zip - firstly zip person to corresponding age then sort and after all generate defaultdict and dictionary comprehension.

from collections import defaultdict
dd= defaultdict(list)
mydict = {'name':['peter', 'janice', 'andy'], 'age':[10, 30, 15]}
d=zip(mydict['name'],mydict['age'])

for i in sorted(d,key=lambda x: x[0]):
    dd['names'].append(i[0])
    dd['age'].append(i[1])
print {k:v for k,v in dd.items()}

Output-

{'age': [15, 30, 10], 'names': ['andy', 'janice', 'peter']}

Yes maybe your approach with the dictionnary isn't the best.Here you're just storing list in a dictionnary. But you may also use a list to store those list. That would be almost the same What i would suggest first is dict of dict.

myPeople = {}
myPeople["peter"] = {"age":20, "country" : "USA"}
myPeople["john"] = {"age":30, "country" : "newzealand"}
myPeople["fred"] = {"age":32, "country" : "France"}
# or if you have only one descript per name to store, 
# you may use only a dict
# myPeopleName["peter"] = 20
# myPeopleName["john"] = 30

#then you iterate the dictionnary as before and the result will be print
# out sorted by key

for k in sorted(myPeople.keys()): 
    print myPeople[k]

Edit : My code was totaly wrong. And collection do not sort value by key but preserve the order of the key which you add in the dictionary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM