[英]why 'functools.reduce' and 'itertools.chain.from_itertools' had different computation time when nested list merged
有時您應該嵌套合並到合並列表(這類似於np.flatten()
)。 當列表列表如下所示時,您應該將其展平
a = [[j for j in range(0, 10)] for i in range(0, 10000)]
您有兩種解決方案可以解決它。 itertools.chain.from_iterable
和functools.reduce
。
%timeit list(itertools.chain.from_iterable(a))
%timeit reduce(lambda x, y: x+y, a)
您認為哪個比另一個更快?
itertools.chain.from_iterable
快1000倍或更多(當列表的長度更大時)。
如果有人知道為什么會這樣,請告訴我。
永遠感謝您的支持和幫助。
是的,因為列表串聯(即使用+
)是O(N)操作。 當您執行此操作以逐步構建大小為N的列表時,它將變為O(N 2 )。
相反,使用chain.from_iterable
將使用list
類型構造函數簡單地遍歷最終列表中的所有N個項目,該構造函數將具有線性性能。
這就是為什么您不應該使用sum
來使列表變平的原因(請注意, reduce(lambda x, y: x+y,...)
只是sum
)。
請注意,扁平化嵌套列表的慣用方式是使用列表理解:
[x for sub in a for x in sub]
這是一種反模式, sum
方法可以防止您使用str
對象:
>>> sum(['here', 'is', 'some', 'strings'], '')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]
請注意,您的reduce
/ sum
方法等效於:
result = []
for sub in a:
result = result + sub
這清楚地顯示了循環中的昂貴+
。 請注意,以下朴素方法實際上具有O(N)行為,而不是O(N 2 ):
result = []
for sub in a:
result += sub
這是因為my_list += something
等同於my_list.extend(something)
,而.extend
(以及.append
)具有攤銷的恆定時間行為,因此總的來說,它將是O(N)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.