2 回答

TA貢獻1993條經驗 獲得超6個贊
老實說-我并不真正了解您的代碼及其背后的想法,因此無法告訴您為什么結果僅包含所需元組的子集。
但是,我有一個不同的方法,你可能會覺得有趣。
主要思想是有一個可以測試兩個元組是否重疊的函數。此函數適用于overlap_list. 如果兩個重疊,則將它們添加到結果列表中,該列表隨后將包含重復項,因此list(set(result))最終應用。但是,您可以將演員表放在列表中,因為一組都可以,因此我可以...
測試函數的想法是簡單地對要測試的兩個元組的 4 個值進行排序并查看排序順序(請參閱 參考資料numpy.argsort)。如果前兩個索引是 0/1 或 2/3,則兩個元組不重疊。
換句話說:針對存在進行測試,>1它們必須是不相等的,即不能同時為真或假:
def overlap_test(tpl1, tpl2):
import numpy as np
a, b = np.argsort(tpl1 + tpl2)[:2] > 1
return a != b
這是使用該函數的循環:
import itertools as it
result = []
for test_tpl, sec_tpl in list(it.combinations(overlap_list, 2)):
if overlap_test(test_tpl, sec_tpl):
result.extend([test_tpl, sec_tpl])
result = list(set(result))
# [(10001657, 10001718),
# (10031556, 10031656),
# (10031548, 10031643),
# (10001657, 10001716),
# (10001656, 10001717)]
我仍然想知道循環是否不能更有效,并且這樣是否也set無法優化對循環的需求 - 好吧,也許你會找到一個更好的循環。
編輯:
到目前為止并沒有真正發現有什么不同,但有一點改進:
相同的方法,但從set一開始就使用:
def find_overlap_tuples_0(tpl_list):
result = set()
for test_tpl, sec_tpl in list(it.combinations(tpl_list, 2)):
if overlap_test(test_tpl, sec_tpl):
result.add(test_tpl)
result.add(sec_tpl)
return list(result)
# %timeit find_overlap_tuples_0(overlap_list)
# 178 μs ± 4.87 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
有點不同,僅基于排列和分組(似乎稍微快一點):
def find_overlap_tuples_1(tpl_list):
result = set()
no_ovl = set()
for a, grp in it.groupby(it.permutations(tpl_list, 2), lambda x: x[0]):
for b in grp:
if (a not in result) and (b[1] not in no_ovl):
if overlap_test(*b):
result.add(b[0])
result.add(b[1])
break
no_ovl.add(b[0])
return list(result)
# %timeit find_overlap_tuples_1(overlap_list)
# 139 μs ± 1.59 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

TA貢獻1898條經驗 獲得超8個贊
似乎您可以對列表進行排序,以便任何重疊的開始和停止都是相鄰的,然后只比較鄰居以確定是否由于不重疊而需要過濾掉任何元組(不需要在代碼末尾進行排序,只是更容易在打印輸出中看到重疊的鄰居)。
l = [(10001656, 10001717), (700, 60000), (10001657, 10001718), (10001657, 10001716), (10031548, 10031643), (10031556, 10031656)]
l.sort()
overlap = set()
for a, b in zip(l, l[1:]):
if a[1] >= b[0] and a[1] <= b[1]:
overlap.add(a)
if b[0] >= a[0] and b[0] <= a[1]:
overlap.add(b)
overlap = sorted(overlap)
print(overlap)
# [(10001657, 10001716), (10001657, 10001718), (10031548, 10031643), (10031556, 10031656)]
添加回答
舉報