簡體   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