繁体   English   中英

Python中的就地字典反转

[英]In-place dictionary inversion in 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

我有一种感觉,除非尺寸增加,否则dict的尺寸永远不会调整,所以你可能需要定期添加+删除虚拟物品。 请参阅收缩率

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

如果算法正确,可能需要数百万条目才能在现代机器上耗尽RAM。 假设这样,您必须使用一些持久存储来使数据一次只处理块。 为什么不使用带有2列的简单数据库表来存储dict?

key  value
1    1999
1    2000
1    2001
2    440
2    441
...

然后,您可以使用任一列作为键, order by在所需列上按order by选择,并使用简单的python代码对来自其他列的值进行分组。

我实际上没有看到任何方式可以显着提高当前算法的内存使用率。 您确实使用迭代器而不是直接创建新的列表/ dicts,因此唯一重要的内存使用来自原始字典和新的反向字典。

如果你没有足够的RAM来运行这个算法与你实际使用的字典,我所能想到的是以某种方式避免同时保留原始字典和倒置字典在内存中。 一种方法是在将原始字典添加到倒置字典时从原始字典中删除项目,这可以这样做:

def invert(old_dict):
    inverted = collections.defaultdict(list)
    while old_dict:
        k,v = old_dict.popitem()
        for vi in v:
            inverted[vi].append(k)
    return inverted

(注意我也使用了defaultdict来简化代码,但如果你真的需要一个纯粹的dict ,而不是一个子类,你可以做一些类似于你最初使用try / except

如果你想在算法完成后保留原始字典和倒置字典,我所能想到的就是将它们存储在磁盘文件中,并找到一种方法只能一次加载一个片段。 我不知道任何能够将dict存储到磁盘并且一次只加载一部分的标准Python模块,因此您可能必须为此编写自己的代码。

我没有直接的答案。 这是我的一些想法。

  1. 我想你想做的事情可以称为倒置索引

  2. 我不相信它可以就地完成,也不认为这是正确的策略。 您应该查看基于磁盘的解决方案。 也许可以对原始数据结构进行排序或组织,将其写入一个或多个文件,然后将其读回并将它们合并到最终的数据结构中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM