Python中的就地字典倒置


问题内容

我需要反转一个列表字典,我不知道该如何用英语准确解释它,因此这里有一些代码可以满足我的需求。只是占用太多内存。

def invert(oldDict):
    invertedDict = {}
    for key,valuelist in oldDict.iteritems():
        for value in valuelist:
            try:
                entry = invertedDict[value]
                if key not in entry:
                    entry.append(key)
            except KeyError:
                invertedDict[value] = [key]
    return invertedDict

原始是列表的字典,结果是列表的字典。这“反转”了它。

test = {}
test[1] = [1999,2000,2001]
test[2] = [440,441]
test[3] = [440,2000]

print invert(test)

这给出:

{2000: [1, 3], 2001: [1], 440: [2, 3], 441: [2], 1999: [1]}

我需要知道这是否可以就地完成,因为我当前的策略超出了我正在使用的词典在计算机上的物理内存量。您能想到一种使用发电机的方法吗?


问题答案:

这不是就地完成,而是通过使用popitem()消耗oldDict

from collections import defaultdict
def invert(oldDict):
    invertedDict = defaultdict(list)
    while oldDict:
        key, valuelist = oldDict.popitem()
        for value in valuelist:
            invertedDict[value].append(key)
    return invertedDict

我有一种感觉,除非增加大小,否则决不会调整字典的大小,因此您可能需要定期添加/删除虚拟项目。见收缩率

from collections import defaultdict
def invert(oldDict):
    invertedDict = defaultdict(list)
    i=0
    while oldDict:
        key, valuelist = oldDict.popitem()
        for value in valuelist:
            invertedDict[value].append(key)
        i+=1
        if i%1000==0: # allow the dict to release memory from time to time
            oldDict[None]=None
            del oldDict[None]
    return invertedDict