简言之:
我注意到,在自定义对象上应用hash()
函数总是返回一个4的倍数加上1的值。这有什么原因吗,以及阻止这种情况发生的方法?
我想,如果总是这样的话,我可以减去1,除以4,得到hash
值的“密集”分布,但我不确定这是否确实如此。
冗长/举例:
在Python
中,我有一堆自定义对象,以及一个(简短)值列表。对于每个对象,我希望在列表中选择一个值,因此,
有些对象将与相同的值配对,这是没有问题的。
我的想法是为此使用对象的hash()
值(它们没有实现用户定义的__hash__
方法),其方式如下:
value = list_of_values[hash(object) % len(list_of_values)]
但是,我注意到,列表中的一些值从未被选中,检查后,hash
值总是4的倍数,加上1--如果list_of_values
的长度是4的倍数,这是一个问题。
我会得到任何一个帮助
hash
函数返回一个不是任何值的倍数的值的方法;或者发布于 2020-01-29 17:38:16
写一个问题集中于头脑是很有趣的。在输入我的问题时,我得到了答案:我首先用素数取hash
值的模,然后取带有列表长度的模:
value = list_of_values[(hash(object) % prime) % len(list_of_values)]
素数应该小于典型的hash
-value,但超过list_of_values
长度的几倍。由于list_of_values
在我的例子中只有不到100个元素,所以我取了7919的值。
(要了解后者为何重要:假设list_of_values
的长度为100,而prime
的值为113
。在这种情况下,第一个模块(hash(object) % prime
)给出的值从0到112,它们都是相同的。然后,如果我使用100
的模,则0..99
的数字保持不变,而这些100..112
被缩减为0..12
。这使得前13个元素被选中的概率是其他元素的两倍。)
发布于 2020-01-29 17:59:54
如果您想要可重复的随机序列,请使用已知值调用random.seed
。
>>> random.seed(3)
>>> [random.choice("abc") for x in range(10)]
['a', 'c', 'c', 'a', 'b', 'c', 'b', 'c', 'c', 'a']
>>> random.seed(3)
>>> [random.choice("abc") for x in range(10)]
['a', 'c', 'c', 'a', 'b', 'c', 'b', 'c', 'c', 'a']
这两份名单是相同的,这不是巧合。
根据您的评论,我认为您可以使用defaultdict
。
>>> from collections import defaultdict
>>> import random
>>> values = [1,2,3,4]
>>> d = defaultdict(lambda: random.choice(values))
>>> [d['foo'] for _ in range(20)]
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
对任何给定密钥的第一次查找都是随机选择的,然后被记住。后续查找总是使用该第一个值。
https://stackoverflow.com/questions/59972456
复制相似问题