还有另一种方法可以避免重复大型可清除对象吗?

时间:2013-08-23 19:17:49

标签: python duplication hashable

我正在处理文本,并且需要存储大量可散列对象 - 有时是字符串,有时是单词元组等。我一直在考虑使用散列函数来提供简单的存储和检索类但是我的第一种方法可能是单个散列键可能会解析为多个项目。鉴于我添加了一个get函数,它将add的返回值作为参数,我无法知道要返回的列表中的哪个项目。

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

另一种方法最终确保每个唯一可清洗项目只有一个映射。

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的方式处理这种情况?

我对这个问题一直不明确。有两个问题 - 一个是我有数百万个目前正在使用密钥的对象,每个密钥的范围从100到1000(big_hashable)。将它们转换为整数可以处理比我目前更多的数据。其次,只保留每个big_hashable东西的单个规范副本也会减少内存使用量,尽管这是推动我的问题的第一个问题,因为每个密钥实际上是big_hashable东西的单独副本。

1 个答案:

答案 0 :(得分:2)

如果您不需要能够有效地检索给定不同副本的对象的规范副本,则可以使用一组:

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

如果您确实需要能够有效地检索对象的规范副本,请不要按哈希值存储它们 - 这会被严重破坏。只需直接使用hashable。

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函数对字符串一样。