15

我有一个嵌套的人员和项目评级字典,以人员为键。人们可能会或可能不会共享项目。例子:

{
 '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}
}

做这个的最好方式是什么?可以理解吗?

4

5 回答 5

24

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}}
于 2010-02-16T14:56:46.317 回答
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()]))])
于 2010-02-16T20:19:30.333 回答
1

这很容易做到(正如其他人所展示的那样),但根据您的需要,您还应该考虑对于您希望通过任何标准提取的具有多条信息的数据,数据库可能是最好的工具。内置sqlite3模块提供了一个低开销的数据库,根据您的操作,它可能比嵌套的字典更好地为您服务。

于 2010-02-16T17:52:25.063 回答
0

Pandas 可以提供另一种选择。假设data是输入字典。

import pandas as pd
output = {i:s.dropna().to_dict() for i, s in pd.DataFrame(data).T.iteritems()}
于 2016-12-24T00:29:09.767 回答
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
于 2017-11-07T06:06:38.963 回答