lst = [ ('Orange', 0.10), ('Apple', 0.05), ('Mango', 0.15), ('etc', 0.69) ]
x = 0.0
lst2 = []
for fruit, chance in lst:
tup = (x, fruit)
lst2.append(tup)
x += chance
tup = (x, None)
lst2.append(tup)
import random
def pick_one(lst2):
if lst2[0][1] is None:
raise ValueError, "no valid values to choose"
while True:
r = random.random()
for x, fruit in reversed(lst2):
if x <= r:
if fruit is None:
break # try again with a different random value
else:
return fruit
pick_one(lst2)
Это создает новый список с возрастающими значениями, представляющими диапазон значений, которые выбирают фрукт; затем pick_one () идет назад по списку, ища значение, которое <= текущее случайное значение. Мы помещаем значение «часовой» в конец списка; если значения не достигают 1,0, существует вероятность случайного значения, которое не должно совпадать ни с чем, и оно будет соответствовать значению дозорного, а затем будет отклонено. random.random () возвращает случайное значение в диапазоне [0.0, 1.0), поэтому в конечном итоге оно обязательно будет соответствовать чему-либо в списке. </p>
Приятно то, что вы должны иметь одно значение с вероятностью совпадения 0,000001, и оно должно фактически совпадать с этой частотой; другие решения, в которых вы создаете список с повторяющимися элементами и просто используете random.choice (), чтобы выбрать один из них, потребовали бы список с миллионом элементов в нем для обработки этого случая.