假設有三個排序串列,A、B、C。
A = [1, 2, 3, 4]
B = [3, 4, 5]
C = [2, 3, 4]
我正在使用itertools.product查找總和小于 10 的所有可能組合。
如果我只有三個串列,我將使用以下代碼。
A = [1, 2, 3, 4] B = [3, 4, 5] C = [2, 3, 4]
for a in A:
for b in B:
for c in C:
if a b c < 10:
print(a, b, c)
else:
break
在這里,每個串列都被排序,因此我使用 break 來提高效率。
但是當我使用itertools.product時,那我怎么使用break呢?我的意思是如何直接進行特定的迭代(例如,a = 3,b = 3,c = 3)?
for a, b, c in itertools.product(A, B, C):
....?
uj5u.com熱心網友回復:
您可以嘗試以下操作:
from itertools import product, dropwhile
A = [1, 2, 3, 4]
B = [3, 4, 5]
C = [2, 3, 4]
for a, b, c in dropwhile(lambda x: x != (3,3,3), product(A, B, C)):
print(a, b, c)
它給:
3 3 3
3 3 4
3 4 2
3 4 3
3 4 4
. . .
請注意,這并沒有真正直接進入給定的迭代。相反,itertools.dropwhile運行迭代器直到滿足指定條件,然后才開始回傳其值。
uj5u.com熱心網友回復:
不可能在 中跳過迭代itertools.product,但考慮到串列已排序,可以通過使用二分搜索和查找小于所需差異的專案并使用記憶來減少迭代次數:
import itertools
import bisect
def bisect_fast(A, B, C, threshold):
seen_b_diff = {}
seen_c_diff = {}
for a in A:
b_diff = threshold - a
if b_diff not in seen_b_diff:
index = bisect.bisect_left(B, b_diff)
seen_b_diff[b_diff] = index
# In B we are only interested in items that are less than `b_diff`
for ind in range(seen_b_diff[b_diff]):
b = B[ind]
c_diff = threshold - (a b)
# In `C` we are only interested in items that are less than `c_diff`
if c_diff not in seen_c_diff:
index = bisect.bisect_left(C, c_diff)
seen_c_diff[c_diff] = index
for ind in range(seen_c_diff[c_diff]):
yield a, b, C[ind]
def naive(A, B, C, threshold):
for a, b, c in itertools.product(A, B, C):
if a b c < threshold:
yield a, b, c
輸出
>>> from random import choice
>>> A, B, C = [sorted([choice(list(range(1000))) for _ in range(250)]) for _ in range(3)]
>>> list(naive(A, B, C, 1675)) == list(bisect_fast(A, B, C, 1675))
True
>>> %timeit list(bisect_fast(A, B, C, 1675))
1.59 s ± 32.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit list(naive(A, B, C, 1675))
3.09 s ± 55.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/348112.html
上一篇:可能是一個關于c 回圈的簡單問題
下一篇:管道可以用于多個班級嗎?
