如何从Python的Counter类中获得加权随机选择? [英] How can I get a weighted random pick from Python's Counter class?

查看:305
本文介绍了如何从Python的Counter类中获得加权随机选择?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,我正在使用 collections.Counter 跟踪各种事物的成功 - 事物递增相应的计数器:

I have a program where I'm keeping track of the success of various things using collections.Counter — each success of a thing increments the corresponding counter:

import collections
scoreboard = collections.Counter()

if test(thing):
    scoreboard[thing]+ = 1

然后,为了将来的测试,我想倾向于那些已经取得最大成功的 thing Counter.elements()似乎是理想的,因为它返回的元素(以任意顺序)重复多次等于计数。所以我想我可以做:

Then, for future tests, I want to skew towards things which have generated the most success. Counter.elements() seemed ideal for this, since it returns the elements (in arbitrary order) repeated a number of times equal to the count. So I figured I could just do:

import random
nextthing=random.choice(scoreboard.elements())

但不,这会引发 TypeError:'itertools.chain'类型的对象没有len ()即可。好的,所以 random.choice 无法与迭代器一起使用。但是,在这种情况下,长度是已知的(或可知) - 它是 sum(scoreboard.values())

But no, that raises TypeError: object of type 'itertools.chain' has no len(). Okay, so random.choice can't work with iterators. But, in this case, the length is known (or knowable) — it's sum(scoreboard.values()).

我知道迭代未知长度列表并随机选择元素的基本算法,但我怀疑有更优雅的东西。我应该在这做什么?

I know the basic algorithm for iterating through a list of unknown length and fairly picking an element at random, but I suspect that there's something more elegant. What should I be doing here?

推荐答案

您可以使用 itertools.islice 获取可迭代的第N项:

You can do this rather easily by using itertools.islice to get the Nth item of an iterable:

>>> import random
>>> import itertools
>>> import collections
>>> c = collections.Counter({'a': 2, 'b': 1})
>>> i = random.randrange(sum(c.values()))
>>> next(itertools.islice(c.elements(), i, None))
'a'

这篇关于如何从Python的Counter类中获得加权随机选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆