我有一系列元素,每个元素都与元组中的权重w
(正整数)相关联。有什么好的方法(最好是基于迭代器的)来创建包含每个元素w_i
的{{1}}个实例的序列或列表?
e_i
答案 0 :(得分:2)
使用带有嵌套循环的列表推导:
unrolled = [c for c, count in weighted for _ in range(count)]
如果您使用的是Python 2,则可以使用xrange()
代替。
如果您喜欢itertools
,可以使用itertools.chain.from_iterable()
将其变为惰性迭代:
from itertools import chain
chain.from_iterable([c] * count for c, count in weighted)
演示:
>>> weighted = [ ("a", 3), ("b", 1), ("c", 4) ]
>>> [c for c, count in weighted for _ in range(count)]
['a', 'a', 'a', 'b', 'c', 'c', 'c', 'c']
>>> from itertools import chain
>>> list(chain.from_iterable([c] * count for c, count in weighted))
['a', 'a', 'a', 'b', 'c', 'c', 'c', 'c']
我使用list()
将chain
迭代器重新转换为序列。
答案 1 :(得分:1)
Counter
内置了这个逻辑,假设顺序并不重要
>>> weighted = [ ("a", 3), ("b", 1), ("c", 4) ]
>>> from collections import Counter
>>> c = Counter(dict(weighted))
>>> list(c.elements())
['a', 'a', 'a', 'c', 'c', 'c', 'c', 'b']
使用itertools(很多)的另一种方式
>>> from itertools import chain, repeat, starmap
>>> list(chain.from_iterable(starmap(repeat, weighted)))
['a', 'a', 'a', 'b', 'c', 'c', 'c', 'c']
答案 2 :(得分:0)
此方法基本上使用生成器表达式和join
创建单个字符串,然后将该字符串转换为list
。
weighted = [ ("a", 3), ("b", 1), ("c", 4) ]
unrolled = list(''.join([letter*count for letter,count in weighted]))
>>> unrolled
['a', 'a', 'a', 'b', 'c', 'c', 'c', 'c']