2012-11-12 52 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))]