如果在第一步中对列表进行排序,您可以进行更高效的比较,并且当第一个比较失败时,可以中断内部循环。因为所有后续的值都会更大。
import itertools
import time
import numpy as np
from itertools import combinations, permutations
from math import isclose
def func1(lats):
pairs = []
lats_sorted = sorted(lats)
for index, lat1 in enumerate(lats_sorted[:-1]):
for lat2 in lats_sorted[index + 1:]:
if lat2 - lat1 <= 0.1:
pairs.append((lat1, lat2))
else:
break
return pairs
def func2(lats):
pairs = []
for i in lats:
for j in lats:
if (i - 0.1) <= j <= (i + 0.1):
pairs.append((i, j))
return pairs
def func3(lats):
pairs = []
for i, j in itertools.combinations(lats, 2):
if (i - 0.1) <= j <= (i + 0.1):
pairs.append((i, j))
return pairs
def func4(lats):
pairs = []
for i in lats:
for j in lats:
if (i - 0.1) <= j <= (i + 0.1) and i != j:
pairs.append((i, j))
return pairs
def func5(lats):
close_lats = [c for c in combinations(lats, 2) if abs(c[0] - c[1]) <= 0.1]
return close_lats
def func6(lats):
pairs = []
lats_sorted = sorted(lats)
i = 0
j = 1
while j < len(lats_sorted):
if lats_sorted[j] - lats_sorted[i] <= 0.1:
for lat in lats_sorted[i:j]:
pairs.append((lat, lats_sorted[j]))
j += 1
else:
i += 1
return pairs
def func7(lats):
pairs = []
for l1, l2 in permutations(lats, r=2):
if isclose(l1, l2, abs_tol=0.1):
pairs.append((l1, l2))
return pairs
lats = np.random.randint(0, 100000, 5000) / 1000
print(lats)
func_list = [func1, func2, func3, func4, func5, func6, func7]
for func in func_list:
start = time.time()
pairs = func(lats)
end = time.time()
print(f"{func.__name__}: time = {end - start} s, pair count = {len(pairs)}")
输出结果为
[94.644 79.527 29.458 ... 50.957 12.598 28.743]
func1: time = 0.03390932083129883 s, pair count = 24752
func2: time = 6.506390333175659 s, pair count = 54686
func3: time = 2.5684497356414795 s, pair count = 24843
func4: time = 6.778799533843994 s, pair count = 49408
func5: time = 3.18171763420105 s, pair count = 24752
func6: time = 0.007977962493896484 s, pair count = 24752
func7: time = 7.56172513961792 s, pair count = 49504
展示提议算法(func6)比其他算法更快,
Ali Moghaddaszadeh。在func1/func6和func3(itertools解决方案)之间的轻微计数差异似乎是数字精度问题。
if i == j: continue
- 0x5453