Sort a multilevel orderdict in Python? - python

I have a dict of type OrderDict as follows:
>>> from collections import OrderedDict
>>> d=OrderedDict()
>>> d['a']=(dict({'key1': 40}))
>>> d['a'].update(dict({'key2': 10}))
>>> d
OrderedDict([('a', {'key1': 40, 'key2': 10})])
>>> d.values()
odict_values([{'key1': 40, 'key2': 10}])
Now, I am trying to sort the created orderDict by the values of the dict, i.e., 10 and 40, but seems it keeps sorting by the keys. Here is what I am doing:
>>> sorted(list(d.values())[0], key=lambda x: x[1])
['key1', 'key2']
I am looking to get this:
{'a': {'key2': 10, 'key1': 40}}

In order to sort a dictionary by value, use d.get as the sort key:
{k: d[k] for k in sorted(d, key=d.get)}

The syntax you're looking for is this:
{k: v for k, v in sorted(d.items(), key=lambda x: x[1])}
This is the equivalent of list comprehension for dictionaries

Related

How can I get list of values of keys in list of dicts in python?

I have a list of dicts:
[{"app1": "value1"},{"app2": "value2"},{"app1": "value3"},{"app1": "value4"}, {"app3": "value5"}]
How can I get all values of a certain key in a list?
So for example for "app1" it should become something like:
{"app1":["value1", "value3", "value4"]}
For "app2" it just becomes:
{"app2":["value2"]}
Use a defaultdict with a nested for loop
from collections import defaultdict
d = defaultdict(list)
lst = [{"app1": "value1"},{"app2": "value2"},{"app1": "value3"},{"app1": "value4"}, {"app3": "value5"}]
for i in lst:
for k,v in i.items():
d[k].append(v)
print(dict(d))
{'app1': ['value1', 'value3', 'value4'], 'app2': ['value2'], 'app3': ['value5']}
You can use a list comprehension to get all the values for a given key:
>>> data = [{"app1": "value1"},{"app2": "value2"},{"app1": "value3"},{"app1": "value4"}, {"app3": "value5"}]
>>> {"app1": [d["app1"] for d in data if "app1" in d]}
{'app1': ['value1', 'value3', 'value4']}
And if you want to accumulate it all into a single dict that's just putting the list comprehension inside a dict comprehension:
>>> {k: [d[k] for d in data if k in d] for d in data for k in d}
{'app1': ['value1', 'value3', 'value4'], 'app2': ['value2'], 'app3': ['value5']}
a = [{"app1": "value1"},{"app2": "value2"},{"app1": "value3"},{"app1": "value4"}, {"app3": "value5"}] #list of dicts
k = "app1" #key to look for
out = {k: []}
for item in a:
for key in list(item):
if key == k:
out[k].append(item[key])
print(out)
{'app1': ['value1', 'value3', 'value4']}

Why key error is combining while combining List of dictionary with same keys

I have a list of dictionary
dictio =[{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
My desired out
{key1:[value1, value2, value3], key2:[value4, value5]}
My code throwing key error
{ k:[d[k] for d in dictio ] for k in dictio[0] }
i got solution from stack
d = {
k: [d.get(k) for d in dictio ]
for k in set().union(*dictio )
}
In this case out is having none
{'k2': [None, None, None, 'v4', 'v5'], 'k1': ['v1', 'v2', 'v3', None, None]}
Try:
{ k:[d[k] for d in dicts if k in d] for k in set().union(*dicts) }
Your code throws, because some dicts don't have all keys (for example key1 in fourth dictionary). if k in d amends that alloing to continue only those, that have.
EDIT: you need to union your dicts as well, otherwise you won't get all keys, only those present in first dictionary.
If you can guarantee the specified order of list items, you can use itertools.groupby:
{k[0]: [d[k[0]] for d in g] for k, g in groupby(d, lambda x: tuple(x))}
Example:
from itertools import groupby
d = [{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
print({k[0]: [d[k[0]] for d in g] for k, g in groupby(d, lambda x: tuple(x))})
# {'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
You iterate over the dictionaries with for d in dict, and each time you use d.get(k). If a dictionary does not contain that key, it returns None, hence these are the Nones in the list.
I suggest you use a defaultdict instead, like:
from collections import defaultdict
result = defaultdict(list)
for subd in mydicts:
for k, v in subd.items():
result[k].append(v)
If you want to get rid of the "default" behavior after constructing the dictionary, you can wrap the result in a new dictionary, like:
result = dict(result)
so for the given sample dictionary, this will yield:
>>> result
defaultdict(<class 'list'>, {'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']})
>>> dict(result)
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
The above will work if dictionaries have multiple keys, etc. Furthermore we only make one pass over the list of dictionaries.
Note: please do not name your variables after builtin functions/classes like dict, since now you overwrite the reference to the dict class.
Code from your original post need slight modification to get it working as intended
dictio =[{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
d = {
k: [d.get(k) for d in dictio if d.get(k) is not None]
for k in set().union(*dictio )
}
print(d)
Output:
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
Note usage of is not None for checking, which according to PEP-8 is the preferred way.
Different way to print
super_dict = {}
for d in dictio:
for l, m in d.items():
super_dict.setdefault(l, []).append(m)
super_dict
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
with collection set
import collections
super_dict1 = collections.defaultdict(set)
for d in dictio:
for k, v in d.items():
super_dict1[k].add(v)
dict(super_dict1)
{'key1': {'value1', 'value2', 'value3'}, 'key2': {'value4', 'value5'}}
list comprehension
combined_key_set= {key for d in dictio for key in d}
su_di = {key : [d[key] for d in dictio if key in d] for key in combined_key_set}
su_di
{'key2': ['value4', 'value5'], 'key1': ['value1', 'value2', 'value3']}
comprehension
{key : [d[key] for d in dictio if key in d] for key in [key for d in dictio for key in d]}

Python convert dict of lists to dict of sets?

I have:
myDict = {'a': [1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
I want:
myDict = {'a': set([1,2,3]), 'b':set([4,5,6]), 'c':set([7,8,9])}
Is there a one-liner I can use to do this rather than looping through it and converting the type of the values?
You'll have to loop anyway:
{key: set(value) for key, value in yourData.items()}
If you're using Python 3.6+, you can also do this:
dict(zip(myDict.keys(), map(set, myDict.values())))
This can be done with map by mapping the values to type set
myDict = dict(map(lambda x: (x[0], set(x[1])), myDict.items()))
Or with either version of dictionary comprehension as well
myDict = {k: set(v) for k, v in myDict.items()}
myDict = {k: set(myDict[k]) for k in myDict}
You can use comprehension for it:
Basically, loop through the key-value pairs and create set out of each value for the corresponding key.
>>> myDict = {'a': [1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
>>> myDict = {k: set(v) for k, v in myDict.items()}
>>> myDict
{'a': {1, 2, 3}, 'b': {4, 5, 6}, 'c': {8, 9, 7}}
You can't do it without looping anyway, but you can have the looping done in one line, with the following code:
myDict = {k:set(v) for k, v in myDict.items()}
This is basically traversing each item in your dictionary and converting the lists to sets and combining the key(str):value(set) pairs to a new dictionary and assigning it back to myDict variable.

How can I sort a defaultdict of list by length of list

I have a defaultdict like:
d = {'a':[1], 'b':[2,3,4], 'c':[5,6]}
I expect:
sorted_d = {'b':[2,3,4], 'c':[5,6], 'a': [1]}
How can I sort it by the length of list?
defaultdicts - like normal dictionaries - don't have order.
If you just want to iterate over it in a sorted way:
for key in sorted(d, key=lambda x:len(d[x]), reverse=True):
...
Dictionaries in python are not ordered.
Use collections.OrderedDict:
>>> d = {'a':[1], 'b':[2,3,4], 'c':[5,6]}
>>> from collections import OrderedDict
>>> OrderedDict(sorted(d.items(), key=lambda item: len(item[1]), reverse=True))
OrderedDict([('b', [2, 3, 4]), ('c', [5, 6]), ('a', [1])])

Sorting keys of same values alphabetically

I have a dictionary where I want to alphabetically sort the keys that have the same value assigned to them.
For example: {chai:1, apple:1, dom banana:1}
How do I sort these keys alphabetically?!
Thanks.
>>> from collections import defaultdict
>>> items = {'chai':1, 'apple':1, 'dom banana':1}
>>> d = defaultdict(list)
>>> for k,v in items.iteritems():
d[v].append(k)
>>> {k:sorted(v) for k,v in d.iteritems()}
{1: ['apple', 'chai', 'dom banana']}
sorted(k for k,v in D.iteritems() if v == 1)

Categories

Resources