我有对象列表“p”,每个对象都有一些数字“a”(例如p [3] .a = 5)。我想从列表中选择随机对象,方式是选择对象的概率与a的值成比例,即选择a = 5的对象的概率是选择a = 1的对象的概率的五倍。我怎么用Python/Pylab/Numpy来做到这一点?Python - 从列表中选择随机对象
谢谢!
我有对象列表“p”,每个对象都有一些数字“a”(例如p [3] .a = 5)。我想从列表中选择随机对象,方式是选择对象的概率与a的值成比例,即选择a = 5的对象的概率是选择a = 1的对象的概率的五倍。我怎么用Python/Pylab/Numpy来做到这一点?Python - 从列表中选择随机对象
谢谢!
这将适用于整数计数,虽然它不会有效的大计数。
c = collections.Counter({k:k.a for k in stuff})
random.choice(list(c.elements()))
下面是一个更有效的方法。
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
我建议使用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))]
而不'Counter'等效方法:'random.choice([X为P X [因为我在范围内(xa)])' – agf