为字符串分配唯一整数id的最有效方法是什么?

时间:2012-03-08 14:56:51

标签: python hash

我编写的程序处理大量的对象,每个对象都有自己唯一的id,它本身就是一串复杂的结构(由一些分隔符连接的对象的十几个独特字段)和大的长度。

由于我必须快速处理很多这些对象,并且我需要在处理时通过id向他们提供这些对象,并且我无权更改其格式(我通过网络从外部检索它们),我想要映射它们的复杂string id到我自己的内部整数id,并进一步用于比较,将它们进一步转移到其他进程等。

我要做的是使用一个简单的dict,其中key作为对象的字符串id,整数值作为我的内部整数id。

我的问题是:Python有更好的方法吗?可能有办法手动计算一些哈希值,不管怎样?可能是dict不是最好的解决方案吗?

至于数字:系统中一次有大约100K这样的独特对象,所以整数容量绰绰有余。

6 个答案:

答案 0 :(得分:10)

为了进行比较,您可以intern字符串,然后将它们与is进行比较,而不是==,它会进行简单的指针比较,并且应该尽可能快(或者比比较两个整数:

>>> 'foo' * 100 is 'foo' * 100
False
>>> intern('foo' * 100) is intern('foo' * 100)
True

intern保证id(intern(A)) == id(intern(B)) iff A == B。输入后请务必intern任意字符串。请注意,{3.}}在Python 3.x中称为intern

但是当你必须将这些字符串传递给其他进程时,你的sys.intern解决方案似乎是最好的。我在这种情况下通常做的是

dict
  

所以整数容量绰绰有余

Python整数是bigint,所以永远不应该成为问题。

答案 1 :(得分:5)

hash功能怎么样?

In [130]: hash
Out[130]: <function hash>

In [131]: hash('foo')
Out[131]: -740391237

没有必要存储哈希值(除非你想):关键是对于值相等的对象它们是相等的(尽管反之亦然) - 毫无疑问,不等的字符串或其他对象散列到相同的值;这是哈希的本质。

如果你知道你的键的范围(你可能也知道),你也可以使用一个完美的哈希函数生成器。这显然是python的一个:http://ilan.schnell-web.net/prog/perfect-hash/

完美哈希保证指定范围内的键与其哈希值具有双射关系。

答案 2 :(得分:4)

您可以使用hashlib算法之一来创建长消息的加密声音摘要,然后将其用作字典键。使用SHA-256的示例:

import hashlib
...
key = hashlib.sha256(longMessage).digest()

与使用hash(longMessage)相比,碰撞的可能性要小得多。

然而,这可能会带来潜在的巨大开销。除非内存使用是一个大问题,否则我只需将原始字符串用作键。

答案 3 :(得分:4)

我为此目的使用了以下内容:

>>> from collections import defaultdict
>>> d = defaultdict(lambda: len(d))
>>> d["cats"]
0
>>> d["cars"]
1
>>> d["cats"]
0

答案 4 :(得分:1)

如果它们存储在内存中,并且您将每个字符串作为对象而不是文本进行比较,我建议使用id(string)来获取唯一的整数。或者,如果你将它们存储在一个dict中,你可以使用带有一组匹配的defaultdict并将它们哈希:

>>> strings = 'a whole lot of strings which may share a hash'.split()
>>> storage = defaultdict(set)
>>> for s in strings:
...     storage[hash(s)].add(s)
>>> storage[hash('a')]
{'a', 'a'}

具体如何实现这取决于你如何使用它们,但基本的想法应该有效。如果您可以发布您尝试做的具体示例,则可能更容易提供更详细的答案。

答案 5 :(得分:1)

dict是一个很好的解决方案。如果您有一种基于字符串ID生成唯一ID的方法,您可以使用双重任务作为自定义字符串类的哈希函数:

class ID_String(str):
    cached_hash = None
    def __hash__(self):
        # custom hash code here
        return custom_hash
    def ID(self):
        if self.cached_hash is None:
            self.cached_hash = self.__hash__()
        return self.cached_hash