2012-11-12 53 views
1

我有对象列表“p”,每个对象都有一些数字“a”(例如p [3] .a = 5)。我想从列表中选择随机对象,方式是选择对象的概率与a的值成比例,即选择a = 5的对象的概率是选择a = 1的对象的概率的五倍。我怎么用Python/Pylab/Numpy来做到这一点?Python - 从列表中选择随机对象

谢谢!

回答

2

这将适用于整数计数,虽然它不会有效的大计数。

c = collections.Counter({k:k.a for k in stuff}) 
random.choice(list(c.elements())) 
+1

而不'Counter'等效方法:'random.choice([X为P X [因为我在范围内(xa)])' – agf

2

下面是一个更有效的方法。

import random 

def weighted_choice(items): 
    # check if no items exist 
    if not items: 
     return None 

    # compute total of all weights 
    total = sum(item.weight for item in items) 

    # select a random point within the total 
    selection = random.randint(0, total - 1) 

    # find the corresponding item 
    count = 0 
    for item in items: 
     count += item.weight 
     if selection < count: 
      return item 
0

我建议使用bisect

from bisect import bisect 

class Element(object): 
    def __init__(self, value): 
     self.a = value 
    def __repr__(self): 
     return 'Element({})'.format(self.a) 

data = [Element(3), Element(5), Element(7), Element(1)] 
last = 0 
breakpoints = [] 
for element in data: 
    breakpoints.append(last + element.a) 
    last += element.a 
print(breakpoints) 

for random_value in xrange(last): 
    pos = bisect(breakpoints, random_value) 
    print(random_value, data[pos]) 

你必须建立与断点列表中只有一次。然后,只要你喜欢,你可以使用它相当快的对分算法。

最后一个循环只是为了演示结果。

编辑:另一种方法得到断点(我不喜欢for循环):

values = [value.a for value in data] 
breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))]