我有一個元素序列,每個元素都與一個元組中的權重w
(一個正整數)相關聯。創建包含每個元素e_i
的w_i
實例的序列或列表有什麼好方法(最好是基於迭代器的)?創建列表元素的多個副本
weighted = [ ("a", 3), ("b", 1), ("c", 4) ]
unrolled = [ "a", "a", "a", "b", "c", "c", "c", "c" ]
我有一個元素序列,每個元素都與一個元組中的權重w
(一個正整數)相關聯。創建包含每個元素e_i
的w_i
實例的序列或列表有什麼好方法(最好是基於迭代器的)?創建列表元素的多個副本
weighted = [ ("a", 3), ("b", 1), ("c", 4) ]
unrolled = [ "a", "a", "a", "b", "c", "c", "c", "c" ]
使用列表中理解嵌套循環:
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
迭代器放回序列。
該方法基本上使用生成器表達式和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']
對不起,但這讓我感到非常迂迴,並且限於(1)個字符串(2)一個字母。有了這麼多的選擇,爲什麼字符串乘法? – alexis 2014-10-29 12:28:31
字符串恰好適合用例。有任何序列的模擬,但是,例如[3] * 3是[3,3,3],所以您可以使用這種方式再次使用序列。在這種情況下,您可以使用'chain.from_iterable'而不是'join'。 – CoryKramer 2014-10-29 12:33:40
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']
我能抽出點的另一種方式,但我很好奇downvoters認爲這個問題是錯誤的。它已經有了一些很好的答案。 – alexis 2014-10-29 12:30:43
我沒有投票,但你沒有顯示任何嘗試自己解決你的問題。 – 2014-10-29 13:08:22