我有一个人和项目评级的嵌套字典,以人为关键。人们可能会也可能不会分享项目。 例如:
{
'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}
}
最好的方法是什么?理解是否可能?
答案 0 :(得分:18)
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}}
答案 1 :(得分: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()]))])
答案 2 :(得分:1)
这很容易做到(正如其他人所示),但根据您的需要,您还应该考虑对于包含您想要按任何标准提取的多条信息的数据,数据库可能是最好的工具。内置的sqlite3
模块提供了一个低开销的数据库,根据您的操作,它可能比嵌套的字典更好地为您提供服务。
答案 3 :(得分:0)
熊猫可以提供另一种选择。假设data
是输入字典。
import pandas as pd
output = {i:s.dropna().to_dict() for i, s in pd.DataFrame(data).T.iteritems()}
答案 4 :(得分:0)
如果您只想访问反向嵌套词典, 如果字典太大而无法反转,请节省内存。
class mdict2(dict):
def __init__(self, parent, key1):
self.parent = parent
self.key1 = key1
def __getitem__(self, key2):
return self.parent.mirror[key2][self.key1]
class mdict(dict):
def __init__(self, mirror):
self.mirror = mirror
def __getitem__(self, key):
return mdict2(self, key)
d0 = {
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
d1 = mdict(d0)
d0['Amy']['item1'] == d1['item1']['Amy']
# True