0

shelveを使って大きな辞書を収納したい。より具体的には、私が持っているのは、マトリックスのような辞書の辞書です。

dict[key1][key2] = value

キーの数は約 5.000 であるため、5.000x5.000 要素のマトリックスを 4Gb のメモリに格納することは不可能です。そのため、シェルブは良い解決策かもしれないと思いました。

それにもかかわらず、辞書の辞書を効率的に構築する方法に関するドキュメントは見つかりませんでした。

これまでのところ、shelve を使用して通常の辞書を含む辞書を作成しました。

def create_entry(key1,key2,value,shelf): # shelf is the opened shelve file
   if key1 not in shelf: # first time we see this key, initialise it
    shelf[key1]={}
   # add the contents
   shelf[key1][key2]=value

それは機能しますが、シェルブを最大限に活用してそれを行うためのより良い方法があるはずです. 何か案は?

4

1 に答える 1

3

ソリューションの唯一の本当の問題は、シェルフが値をピクルして保存することです。そのため、ディスクにページオフするたびに、第 2 レベルの辞書のそれぞれをピクルしてピクルを解除する必要があり、パフォーマンスが大幅に低下する可能性があります。(もちろん、各第 2 レベルの dict はメモリに収まる必要がありますが、それはおそらく問題ではありません。)

それが問題でなければ、あなたがしていることは問題ありません。しかし、そうであれば、他に 2 つの選択肢があります。

棚上げよりも複雑なデータベースを使用して、その周りに独自のラッパーを構築できます。

または、はるかに単純です。ペアをキーとして単一レベルの辞書を使用するだけです。

def create_entry(key1, key2, value, shelf):
    shelf[(key1, key2)] = value

これの欠点は、たとえば、サブディクショナリ内のすべてのキーまたは値を反復する必要がある場合、key1シェルフ全体を反復する必要があることです。それほど複雑ではありませんが ( (key2 for key1, key2 in shelf if key1 == key))、かなり遅くなります。


shelveキーは文字列でなければならないため、上記のコードは実際には では直接機能しません。しかし、それをまとめる非常に簡単な方法があります。値を pickle および unpickle するのと同じようshelveに、キーを文字列化して解析するよりもラッパーを書くことができます。

def _mapkey(self, key):
    return ','.join(map(str, key))
def _unmapkey(self, key):
    return tuple(map(int, key.split(',')))
def __getitem__(self, key):
    return self.shelf[self._mapkey(key)]
def __iter__(self):
    return map(self._unmapkey, self.shelf)
# etc.

効率のために、コード化できるように を生成するのではなく、基になるキーの をshelve生成するだけで済むように、フォークまたはサブクラス化する方がよい場合があります。次に、これを行うことができます:bytesdbmstrshelve

def _mapkey(self, key):
    return struct.pack('>II', key)
def _unmapkey(self, key):
    return struct.unpack('<II', key)
于 2013-05-29T17:50:13.587 に答える