我会假设一个项目的分数不会改变,并且项目是唯一的。
获得随机加权项的最佳方法是索引到累积权重列表中。
要获取样本,请继续选择随机项目,直到您有足够的唯一值。
代码:
from bisect import bisect_left
from itertools import accumulate
from random import random, shuffle
class WeightedRandom:
def __init__(self, items, weights):
self.items = list(items)
self.weights = list(weights)
self.cum_wt = list(accumulate(weights))
self.total_wt = self.cum_wt[-1]
def random(self):
value = random() * self.total_wt
index = bisect_left(self.cum_wt, value)
return self.items[index]
def sample(self, n):
items = set()
while len(items) < n:
items.add(self.random())
# Note: casting from set to list introduces
# an ordering bias; we have to remove this bias.
items = list(items)
shuffle(items)
return items
然后
>>> roulette = WeightedRandom("ABCDEFGHIJ", range(1, 11))
>>> for i in range(10):
... print(roulette.sample(2))
['J', 'D']
['J', 'C']
['I', 'F']
['C', 'H']
['J', 'E']
['A', 'G']
['J', 'H']
['E', 'I']
['I', 'D']
['E', 'I']
但请注意,如果前 (n - 1) 个项目的总和占 total_wt 的很大一部分,sample 可能需要很长时间才能运行!