selection based on percentage weighting

后端 未结 13 2161
忘掉有多难
忘掉有多难 2020-12-04 13:40

I have a set of values, and an associated percentage for each:

a: 70% chance
b: 20% chance
c: 10% chance

I want to select a value (a, b, c) based

13条回答
  •  广开言路
    2020-12-04 14:10

    import random
    
    def selector(weights):
        i=random.random()*sum(x for x,y in weights)
        for w,v in weights:
            if w>=i:
                break
            i-=w
        return v
    
    weights = ((70,'a'),(20,'b'),(10,'c'))
    print [selector(weights) for x in range(10)] 
    

    it works equally well for fractional weights

    weights = ((0.7,'a'),(0.2,'b'),(0.1,'c'))
    print [selector(weights) for x in range(10)] 
    

    If you have a lot of weights, you can use bisect to reduce the number of iterations required

    import random
    import bisect
    
    def make_acc_weights(weights):
        acc=0
        acc_weights = []
        for w,v in weights:
            acc+=w
            acc_weights.append((acc,v))
        return acc_weights
    
    def selector(acc_weights):
        i=random.random()*sum(x for x,y in weights)
        return weights[bisect.bisect(acc_weights, (i,))][1]
    
    weights = ((70,'a'),(20,'b'),(10,'c'))
    acc_weights = make_acc_weights(weights)    
    print [selector(acc_weights) for x in range(100)]
    

    Also works fine for fractional weights

    weights = ((0.7,'a'),(0.2,'b'),(0.1,'c'))
    acc_weights = make_acc_weights(weights)    
    print [selector(acc_weights) for x in range(100)]
    

提交回复
热议问题