将列表中的值与所有其他值进行比较。

3

我有一个纬度列表,lats。我正在尝试比较每个纬度与其他纬度,并找到列表项之间相差0.01以内的每个组合。目前我的代码可以做到这一点,但它也将每个列表值与其自身进行比较。

lats = [79.826, 79.823, 79.855, 79.809]

for i in lats:
    for j in lats:
        if (i - 0.1) <= j <= (i + 0.1):
            print(str(i) +" and "+ str(j))

这将返回输出:

79.826 and 79.826
79.826 and 79.823
79.826 and 79.855
79.826 and 79.809
79.823 and 79.826
79.823 and 79.823
79.823 and 79.855
79.823 and 79.809
79.855 and 79.826
79.855 and 79.823
79.855 and 79.855
79.855 and 79.809
79.809 and 79.826
79.809 and 79.823
79.809 and 79.855
79.809 and 79.809

你可以在if语句中添加另一个条件来检查i是否等于j。 - Devansh Singh
if i == j: continue - 0x5453
你对这个订单感兴趣吗? - norok2
6个回答

6
你正在隐式计算叉积; 你可以写成
for i, j in itertools.product(lats, repeat=2):
    if i - 0.1 <= j <= 1 + 0.1:
        ...

相反,你想要的是列表中的 2 元素 组合

for i, j in itertools.combinations(lats, 2):

1

要遍历和生成lats组合,尽管itertools解决方案应该是首选的方法,但您可能会对某种手动编码的方式感兴趣。假设您真正想要的只是任何两个lats按任意顺序出现,但不重复,您可以简单地逐步限制第二个循环:

for i, x in enumerate(lats):
    for y in lats[i + 1:]:
        ...

此外,当前写的条件比实际需要的复杂了一些。 你实际上想要的是,两个数值 xy 的差值小于某个值 d,因此可以这样写条件:

(x - d) <= y <= (x + d):

作为:

abs(x - y) <= d

0

有一种简洁的版本使用 itertools.combinationsabs

from itertools import combinations
lats = [79.826, 79.823, 79.855, 79.809]
print([c for c in combinations(lats, 2) if abs(c[0] - c[1]) > 0.01])

这将提供:

[(79.826, 79.855), (79.826, 79.809), (79.823, 79.855), (79.823, 79.809), (79.855, 79.809)]

或者带有格式:

from itertools import combinations
lats = [79.826, 79.823, 79.855, 79.809]
close_lats = [c for c in combinations(lats, 2) if abs(c[0] - c[1]) > 0.01]
for combo in close_lats:
    print(f"{combo[0]} and {combo[1]}")

提供:

79.826 and 79.855
79.826 and 79.809
79.823 and 79.855
79.823 and 79.809
79.855 and 79.809

另外,你的问题说你寻找相差不超过0.01的那些数,但是你的代码示例似乎是在寻找相差不超过0.1的数。


0

为了提高效率,您可以使用itertools中的组合迭代器之一(取决于您想要的最终结果)和数学模块中的isclose

from itertools import permutations
from math import isclose

lats = [79.826, 79.823, 79.855, 79.809]

for l1, l2 in permutations(lats, r=2):
    if isclose(l1, l2, rel_tol=0.01):
        print(f"{l1} and {l2}")

输出:

79.826 and 79.823
79.826 and 79.855
79.826 and 79.809
79.823 and 79.826
79.823 and 79.855
79.823 and 79.809
79.855 and 79.826
79.855 and 79.823
79.855 and 79.809
79.809 and 79.826
79.809 and 79.823
79.809 and 79.855

0

我认为您应该先更改算法以解决问题,并避免计算多个纬度(例如79.826和79.82379.823和79.826),其次提高代码性能并将复杂性从O(n^2)降至O(nlog(n))(用于对列表进行排序)。

最好对纬度列表进行排序,并设置两个指针以跟踪列表的下限和上限,其中的项在0.1范围内。

以下是代码:

lats = [79.826, 79.823, 79.855, 79.809]
lats.sort()

i = 0
j = 1
while j < len(lats):
    if lats[j] - lats[i] <= 0.1:
        print(lats[i: j], lats[j])
        j += 1
    else:
        i += 1

输出:

[79.809] 79.823
[79.809, 79.823] 79.826
[79.809, 79.823, 79.826] 79.855

0
如果在第一步中对列表进行排序,您可以进行更高效的比较,并且当第一个比较失败时,可以中断内部循环。因为所有后续的值都会更大。
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解决方案)之间的轻微计数差异似乎是数字精度问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接