, основанный на других решениях, вы генерируете накопительное распределение (как целое или плавающее, как вам нравится), тогда вы можете использовать bisect, чтобы сделать его быстрым
, это простой пример (здесь я использовал целые числа)
l=[(20, 'foo'), (60, 'banana'), (10, 'monkey'), (10, 'monkey2')]
def get_cdf(l):
ret=[]
c=0
for i in l: c+=i[0]; ret.append((c, i[1]))
return ret
def get_random_item(cdf):
return cdf[bisect.bisect_left(cdf, (random.randint(0, cdf[-1][0]),))][1]
cdf=get_cdf(l)
for i in range(100): print get_random_item(cdf),
функция get_cdf
преобразует ее из 20, 60, 10, 10 в 20, 20 + 60, 20 + 60 + 10, 20 + 60 + 10 + 10
теперь мы выбираем случайное число до 20 + 60 + 10 + 10 с использованием random.randint
, затем мы используем bisect для быстрого получения фактического значения