A weighted version of random.choice

后端 未结 25 1940
闹比i
闹比i 2020-11-21 06:29

I needed to write a weighted version of random.choice (each element in the list has a different probability for being selected). This is what I came up with:



        
25条回答
  •  终归单人心
    2020-11-21 06:50

    1. Arrange the weights into a cumulative distribution.
    2. Use random.random() to pick a random float 0.0 <= x < total.
    3. Search the distribution using bisect.bisect as shown in the example at http://docs.python.org/dev/library/bisect.html#other-examples.
    from random import random
    from bisect import bisect
    
    def weighted_choice(choices):
        values, weights = zip(*choices)
        total = 0
        cum_weights = []
        for w in weights:
            total += w
            cum_weights.append(total)
        x = random() * total
        i = bisect(cum_weights, x)
        return values[i]
    
    >>> weighted_choice([("WHITE",90), ("RED",8), ("GREEN",2)])
    'WHITE'
    

    If you need to make more than one choice, split this into two functions, one to build the cumulative weights and another to bisect to a random point.

提交回复
热议问题