反转嵌套字典的Pythonic方法
我有一个嵌套的字典,里面记录了人和他们对物品的评分,字典的键是人名。不同的人可能会对同样的物品进行评分。
{
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
我想找一个最简单的方法,把这些关系反转过来,生成一个新的嵌套字典,这次用物品作为键。
{'item1' : {'Bob':3, 'Jim':6, 'Amy':6},
'item2' : {'Bob':8, 'Amy':5},
'item3' : {'Bob':6, 'Amy':9},
'item4' : {'Jim':7, 'Amy':2}
}
有什么好的方法可以做到这一点吗?用列表推导式可以实现吗?
5 个回答
1
这件事其实很简单(其他人也已经展示过了),不过根据你的需求,你可能还需要考虑一下,如果你有很多信息需要提取,并且是根据不同的条件来提取的话,使用数据库可能是最好的选择。内置的 sqlite3
模块提供了一个轻量级的数据库,根据你的具体情况,它可能比用嵌套字典更适合你。
4
我完全同意Ryan Ginstrom的回答是最好的做法(在实际应用中)。
但是因为问题也明确问了:
用列表推导式可以做到吗?
所以我想分享一个简单的例子,展示如何用列表推导式来实现这个功能(这也可以作为一个好例子,说明嵌套的列表推导式是如何让代码变得难以阅读的)。
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()]))])
27
collections.defaultdict 让这件事变得非常简单:
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))
输出结果:
{'item1': {'Amy': 6, 'Bob': 3, 'Jim': 6},
'item2': {'Amy': 5, 'Bob': 8},
'item3': {'Amy': 9, 'Bob': 6},
'item4': {'Amy': 2, 'Jim': 7}}