This works:
import random
def weighted_choice(weights):
choice = random.random() * sum(weights)
for i, w in enumerate(weights):
choice -= w
if choice < 0:
return i
weighted_choice([.3, .5, .2]) # returns 0,1,2 in proportion to the weight
To test it:
import collections
c = collections.Counter()
n = 1000000
for i in range(n):
c[weighted_choice([.3, .5, .2])] += 1
for k, v in c.items():
print '{}: {:.2%}'.format(k,float(v)/n)
Prints:
0: 30.11%
1: 50.08%
2: 19.81%
The advantage, besides being fairly fast, is that 1) the list elements do not need to add up to 1 or 100, 2) for more choices, just add more elements to the list:
for i in range(n):
c[weighted_choice([.3,.35,.1,.1,.15,.4])]+=1
Prints:
0: 21.61%
1: 25.18%
2: 7.22%
3: 7.03%
4: 10.57%
5: 28.38%
(Timed against the accepted answer, it is about 2x faster...)