0

私はテキストを処理しており、ハッシュ可能なオブジェクトの大きなシーケンスを保存する必要があります-時には文字列、時には単語のタプルなどです.ハッシュ関数を使用して単純なストアと取得クラスを提供することを考えていましたが、私の最初のアプローチでは1 つのハッシュ キーが複数のアイテムに解決される可能性があります。add の戻り値を引数として取る get 関数を追加すると、リスト内のどの項目を返すかわかりません。

class HashStore:
    def __init__(self):
        self.uniques = {}

    def add(self, big_hashable):
        hash_value = hash(big_hashable)
        if hash_value not in self.uniques:
            self.uniques[hash_value] = [big_hashable]
        elif big_hashable not in self.uniques[hash_value]:
            self.uniques[hash_value].append(big_hashable)

        return hash_value

別のアプローチでは、一意のハッシュ可能なアイテムごとに 1 つのマッピングのみが存在することが保証されます。

class SingleStore:
    def __init__(self):
        self.uniques = {}
        self.indexed = {}
        self.index = 0

    def add(self, big_hashable):
        if big_hashable not in self.uniques:
            self.index += 1
            self.uniques[big_hashable] = self.index
            self.indexed[self.index] = big_hashable

        return self.uniques[big_hashable]

これは機能し、add の戻り値を使用して一意の値を返すことが保証されます。少し不器用なようです。この状況を処理するためのより良い、より Pythonic な方法はありますか?

私は質問に関してあいまいでした。2 つの問題があります。1 つは、現在、それぞれ数百から数千バイトの範囲のキーを使用している何百万ものオブジェクトがあることです (big_hashable のもの)。それらを整数に変換すると、現在よりも多くのデータを処理できるようになります。第二に、各 big_hashable の単一の正規コピーのみを保持すると、メモリ使用量も削減されますが、各キーは実際には big_hashable の個別のコピーであるため、私の質問を引き起こしている最初の問題です。

4

1 に答える 1

2

別のコピーが与えられたオブジェクトの正規コピーを効率的に取得できる必要がない場合は、単にセットを使用できます。

s = set()
s.add(3)
s.add(3)
# s only has one 3 in it

オブジェクトの正規のコピーを効率的に取得できるようにする必要がある場合は、それらをハッシュ値で保存しないでください。これはひどく壊れてしまいます。ハッシュ可能なものを直接使用してください。

class Interner(object):
    def __init__(self):
        self._store = {}
    def canonical_object(self, thing):
        """Returns a canonical object equal to thing.

        Always returns the same result for equal things.

        """

        return self._store.setdefault(thing, thing)

モジュールを使用すると、これを改善して、組み込み関数が文字列に対して行うweakrefように、クライアント コードがそれを手放す場合に標準オブジェクトを保持しないようにすることができます。intern

于 2013-08-23T19:27:50.700 に答える