views:

145

answers:

3

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?

+13  A: 

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}}
Ryan Ginstrom
A: 

This is easy enough to do (as others have shown), but depending on your needs you should also consider that for data with several pieces of information where you want to extract by any criterion, a database might be the best tool. The built-in sqlite3 module provides a low-overhead database that may, depending on what you are doing, serve you better than a nested dict.

Mike Graham
this is true, and worth considering. But the data I get could come from a variety of sources (json, xml, db, etc) so I was looking at ways to approach things using language constructs instead of relying on the source.
GSto
+2  A: 
ChristopheD
nice. it does look like a pretty hairy comprehension, but +1 for providing it.
GSto