我想学习如何选择加权项目。例如:我想从池中提取问题,但如果有人无法正确回答问题,则会导致此问题加倍,并增加以后再次选择的可能性。
答案 0 :(得分:3)
有一个保持项目的类:哈希表中的权重对(key = item:value = weight)。
该类还应该保留一个total_weight
变量,它是散列表中所有权重的总和。对于项目,类add_item
,remove_item
和update_weight
的方法应该更新total_weight。这避免了必须重新计算每个选择的总数。
选择项目:
使用1<=random_number<=total_weight
的随机数。
迭代项目:哈希表中的权重对,对权重求和,直到随机数为&lt; =运行总和。当发生这种情况时,您所在的对的关键是所选项目。
这就像滚动一个假想的骰子,其尺寸是所有砝码的总和。对于每个卷,每个项目在模具上都有自己的数字范围,每个范围的大小等于其项目的重量。如果滚动结果属于项目范围,则该项目是所选项目。
编辑以在请求中添加以下示例代码,如下所示。使用Python 2.5.2进行测试:
from random import randint # Import randint function from random module.
class WeightedCollection(object):
def __init__(self):
self.total_weight = 0
self.items = {} # This is a python dictionary == a hash table
def add_item(self, item, weight):
self.items[item] = weight
self.total_weight += weight
def remove_item(self, item):
self.total_weight -= self.items[item] # Subtracts the weight.
del(self.items[item])
def update_weight(self, item, new_weight):
self.total_weight += (new_weight - self.items[item])
self.items[item] = new_weight
def get_random_item(self):
''' Returns random selection but weighted by item weights. '''
# Result of call below is 1 <= random_number <= self.total_weight...
random_number = randint(1, self.total_weight)
sum_so_far = 0
# For every item and its weight...
for item, weight in self.items.iteritems():
sum_so_far += weight
if random_number <= sum_so_far:
return item
# Usage demo...
questions = WeightedCollection()
questions.add_item('What is your name?', 1)
questions.add_item('What is your favorite color?', 50)
questions.add_item('What is the meaning to life?', 100)
print 'Here is what the dictionary looks like:'
print questions.items
print ''
print "Total weight:", questions.total_weight
print ''
print 'Some sample random picks...'
for i in range(5):
print questions.get_random_item()
这是输出:
Here is what the dictionary looks like:
{'What is the meaning to life?': 100, 'What is your name?': 1, 'What is your favorite color?': 50}
Total weight: 151
Some sample random picks...
What is your favorite color?
What is the meaning to life?
What is the meaning to life?
What is your favorite color?
What is the meaning to life?
答案 1 :(得分:2)
保留一系列候选项目。如果一个物品的重量为2,则将其放入阵列两次,一般如果一个物体有重量,则将其放入n次。然后从数组中选择一个随机元素。 TA-daaa。
答案 2 :(得分:2)
看看这个this(向下滚动代码)。
编辑评论家:)
我链接的这个线程上的代码显示了如何实现实际使用权重的二叉树方法,并且不存储数组中的大量元素以实现加权概率。 然后,当权重经常变化时效率非常低,因为每次权重变化时都必须重新创建二叉树。
<强> EDIT2 强>:
请参阅Todd Owen关于使用自平衡树的帖子。每次重量变化时,树显然都需要重新创建不。该部分不包含在我链接的实现中,如果权重变化很大,则需要添加。
答案 3 :(得分:2)
我喜欢@AndréHoffmann关于使用二叉树的想法,其中每个叶节点对应一个问题,并且每个中间节点存储其子节点的权重之和。但他说每次重量变化时都需要重新创建树。
实际上,情况并非如此!当您更改给定叶子的权重时,您只需要更新它与树根之间的那些节点的权重。但是......如果你想修改它,你还需要一些方法来查找树中的节点。
所以我的建议是使用自平衡二叉树(例如红黑树,AVL树等),它按问题ID排序。树上的操作需要保持任何节点的权重等于其子节点权重之和的属性。
使用此数据结构,根节点的权重 W 等于所有问题的权重之和。您可以通过问题ID或随机权重(零和 W 之间)检索问题。此操作以及插入,删除或更新问题的权重均为O(log n )。