我编写的程序处理大量的对象,每个对象都有自己唯一的id,它本身就是一串复杂的结构(由一些分隔符连接的对象的十几个独特字段)和大的长度。
由于我必须快速处理很多这些对象,并且我需要在处理时通过id向他们提供这些对象,并且我无权更改其格式(我通过网络从外部检索它们),我想要映射它们的复杂string id到我自己的内部整数id,并进一步用于比较,将它们进一步转移到其他进程等。
我要做的是使用一个简单的dict,其中key作为对象的字符串id,整数值作为我的内部整数id。
我的问题是:Python有更好的方法吗?可能有办法手动计算一些哈希值,不管怎样?可能是dict不是最好的解决方案吗?
至于数字:系统中一次有大约100K这样的独特对象,所以整数容量绰绰有余。
答案 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