I have a nested dictionary of people and item ratings, with people as the key. people may or may not share items. Example:
{
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
I'm looking for the simplest way to flip these relations, and have a new nested dictionary with items as the key. Example:
{'item1' : {'Bob':3, 'Jim':6, 'Amy':6},
'item2' : {'Bob':8, 'Amy':5},
'item3' : {'Bob':6, 'Amy':9},
'item4' : {'Jim':7, 'Amy':2}
}
What is the best way to do this? Is it possible with a comprehension?
Basically the same way you would flatten a nested list, you just have to do the extra work for iterating the dict by key/value, creating new keys for your new dictionary and creating the dictionary at final step. For Python >= 3.3, change the import to from collections.
1) Using OrderedDict() and items() method Later you make use of a reversed() function which is an in-built python method that takes an argument as the sequence data types like tuple, lists, dictionaries, etc and returns the reverse of it. Remember that reversed() method does not modify the original iterator.
collections.defaultdict makes this pretty simple:
from collections import defaultdict
import pprint
data = {
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
flipped = defaultdict(dict)
for key, val in data.items():
for subkey, subval in val.items():
flipped[subkey][key] = subval
pprint.pprint(dict(flipped))
Output:
{'item1': {'Amy': 6, 'Bob': 3, 'Jim': 6},
'item2': {'Amy': 5, 'Bob': 8},
'item3': {'Amy': 9, 'Bob': 6},
'item4': {'Amy': 2, 'Jim': 7}}
I totally agree that Ryan Ginstrom's answer is the preferred way of doing this (for all practical purposes).
But since the question also explicitely asks:
Is it possible with a comprehension?
I thought I'd chime in with a quick example as for how to do this with a list comprehension (it could be a good example for showing how nested list comphrehensions can quickly decrease readability).
import itertools
d = {
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
print dict([(x, dict([(k, d[k][x]) for k,v in d.items() if x in d[k]]))
for x in set(itertools.chain(*[z for z in d.values()]))])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With