用于无视排序的项目集合的哈希函数
Hash function for collection of items that disregards ordering
我正在使用 hash()
函数来获取包含两个整数和两个字符串的对象的哈希值。此外,我有一本字典,用于存储这些对象;这个过程是我检查对象是否存在哈希值,如果是我更新如果不是我插入新的。
问题是在创建对象时,我不知道对象变量的顺序,无论这些变量的顺序如何,我都想将对象视为相同的。
有没有不考虑变量顺序的hash()
函数的替代函数?
#Consequently what I want is:
hash((int1,str1,int2,str2)) == hash((int2,str2,int1,str1))
您可以使用 frozenset
而不是元组:
>>> hash(frozenset([1, 2, 'a', 'b']))
1190978740469805404
>>>
>>> hash(frozenset([1, 'a', 2, 'b']))
1190978740469805404
>>>
>>> hash(frozenset(['a', 2, 'b', 1]))
1190978740469805404
但是,从可迭代对象中删除重复项会带来一个微妙的问题:
>>> hash(frozenset([1,2,1])) == hash(frozenset([1,2,2]))
True
您可以通过使用 collections.Counter
从可迭代对象创建一个计数器并在计数器的项目上调用 frozenset
来解决此问题,从而保留原始可迭代对象中每个项目的计数:
>>> from collections import Counter
>>>
>>> hash(frozenset(Counter([1,2,1]).items()))
-307001354391131208
>>> hash(frozenset(Counter([1,1,2]).items()))
-307001354391131208
>>>
>>> hash(frozenset(Counter([1,2,1]).items())) == hash(frozenset(Counter([1,2,2]).items()))
False
通常对于这样的事情,如果你 post 一些示例代码,它会有不可估量的帮助,但我假设你有这样的东西:
class Foo():
def __init__(self, x, y):
self.x = x
self.y = y
def __hash__(self):
return hash((self.x, self.y))
你在那里对一个元组进行散列,它确实关心顺序。如果您希望哈希不关心整数的顺序,则只需使用 frozenset:
def __hash__(self):
return hash(frozenset([self.x, self.y]))
如果值的范围不是太大,您可以将它们加在一起,这样可以忽略顺序,但是它确实增加了 2 个哈希值具有相同值的可能性:
def hash_list(items):
value = 0
for item in items:
value+= hash(item)
return value
hash_list(['a', 'b', 'c'])
>>> 8409777985338339540
hash_list(['b', 'a', 'c'])
>>> 8409777985338339540
我正在使用 hash()
函数来获取包含两个整数和两个字符串的对象的哈希值。此外,我有一本字典,用于存储这些对象;这个过程是我检查对象是否存在哈希值,如果是我更新如果不是我插入新的。
问题是在创建对象时,我不知道对象变量的顺序,无论这些变量的顺序如何,我都想将对象视为相同的。
有没有不考虑变量顺序的hash()
函数的替代函数?
#Consequently what I want is:
hash((int1,str1,int2,str2)) == hash((int2,str2,int1,str1))
您可以使用 frozenset
而不是元组:
>>> hash(frozenset([1, 2, 'a', 'b']))
1190978740469805404
>>>
>>> hash(frozenset([1, 'a', 2, 'b']))
1190978740469805404
>>>
>>> hash(frozenset(['a', 2, 'b', 1]))
1190978740469805404
但是,从可迭代对象中删除重复项会带来一个微妙的问题:
>>> hash(frozenset([1,2,1])) == hash(frozenset([1,2,2]))
True
您可以通过使用 collections.Counter
从可迭代对象创建一个计数器并在计数器的项目上调用 frozenset
来解决此问题,从而保留原始可迭代对象中每个项目的计数:
>>> from collections import Counter
>>>
>>> hash(frozenset(Counter([1,2,1]).items()))
-307001354391131208
>>> hash(frozenset(Counter([1,1,2]).items()))
-307001354391131208
>>>
>>> hash(frozenset(Counter([1,2,1]).items())) == hash(frozenset(Counter([1,2,2]).items()))
False
通常对于这样的事情,如果你 post 一些示例代码,它会有不可估量的帮助,但我假设你有这样的东西:
class Foo():
def __init__(self, x, y):
self.x = x
self.y = y
def __hash__(self):
return hash((self.x, self.y))
你在那里对一个元组进行散列,它确实关心顺序。如果您希望哈希不关心整数的顺序,则只需使用 frozenset:
def __hash__(self):
return hash(frozenset([self.x, self.y]))
如果值的范围不是太大,您可以将它们加在一起,这样可以忽略顺序,但是它确实增加了 2 个哈希值具有相同值的可能性:
def hash_list(items):
value = 0
for item in items:
value+= hash(item)
return value
hash_list(['a', 'b', 'c'])
>>> 8409777985338339540
hash_list(['b', 'a', 'c'])
>>> 8409777985338339540