用于无视排序的项目集合的哈希函数

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