【问题标题】:Pairwise Euclidean distance from a list of points点列表的成对欧几里得距离
【发布时间】:2018-08-05 09:50:53
【问题描述】:

我正在尝试编写一个 Python 函数(不使用模块),它将遍历坐标列表并找到两个后续点之间的欧几里德距离(例如,点 a 和 b、b 和c、c 和 d 等)。经过几个小时的搜索,我遇到了this post,我认为它解决了我的问题,所以我写了这个:

myList = [[2, 3], [3,4], [4,5], [5,6], [6,7]]

def distance(pointOne,pointTwo):
    eucDist = ((pointOne[0] - pointTwo[0])**2 + (pointOne[1] - pointTwo[1])**2)**0.5
    return eucDist

def totalDistance(inputPoints):
    dist = []
    for item in inputPoints[1:]:
        coordDist = distance(inputPoints[0],item)
        dist.append(coordDist)
    return sum(dist)

print totalDistance(myList)

但是,这会检索第一个点与其他每个点之间的距离。我一直在试图弄清楚如何为序列中的下一个点定义一个变量,但我对 Python 还是很陌生,只是不太明白如何到达那里。我目前正在编写这样的totalDistance 函数:

def totalDistance(inputPoints):
    dist = []
    for item in inputPoints:
        pOne = item
        pTwo = 
        coordDist = distance(pOne,pTwo)
        dist.append(coordDist)
    return sum(dist)

但不知道如何定义 pTwo。

【问题讨论】:

  • 关键是循环点对:for p1, p2 in zip(points[:-1], points[1:]): ...
  • @RaymondHettinger 嗯,我很惊讶。你真的更喜欢zip(points, points[1:])吗?
  • @StefanPochmann 不,我更喜欢你的版本。也就是说,将两个长度相等的列表压缩在一起更容易解释。

标签: python python-2.7 for-loop iteration point


【解决方案1】:

使用list comprehensionzip 可以这样做:

代码:

def distance(point_one, point_two):
    return ((point_one[0] - point_two[0]) ** 2 +
            (point_one[1] - point_two[1]) ** 2) ** 0.5

def total_distance(points):
    return sum(distance(p1, p2) for p1, p2 in zip(points, points[1:]))

或者对于 Python 3(来自 cmets)使用 map

def total_distance(points):
    return sum(map(distance, points, points[1:]))

测试代码

my_points = [[2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]
print(total_distance(my_points))

结果:

5.656854249492381

【讨论】:

  • 注意,map 实际上是在 callable 之后使用 *args,它的工作原理和 zip! 完全一样,所以你可以这样做:sum(map(distance, data, data[1:]))
  • 谢谢!这是一种比我最初做的更简单、更优雅的解决问题的方法,非常有用。
  • @juanpa.arrivillaga,非常感谢。这很漂亮。
  • @juanpa.arrivillaga 不,这不起作用,它崩溃了。 map doesn't 与 Python 2 中的 zip 完全一样,问题被标记为。
【解决方案2】:

使用 itertools 和 NumPy:

from itertools import tee
import numpy as np

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def total_dist(points):
    return np.sum(np.sqrt(np.sum(np.square(
                  np.diff(tuple(pairwise(points)))), axis=-2)))

total_dist(myList)
# 5.656854249492381

【讨论】:

    【解决方案3】:

    这样做的一种方法是:

    def totalDistance(inputPoints):
        dist = []
        pTwo = inputPoints[0]
        for item in inputPoints[1:]:
            pOne = pTwo
            pTwo = item
            coordDist = distance(pOne,pTwo)
            dist.append(coordDist)
        return sum(dist)
    

    基本上,记录第一项,并从列表中的第二项开始迭代。最好交换 pOnepTwo 以便更容易理解,或者更清楚并使用更多 Pythonic 名称:

    def totalDistance(input_points):
        dist = []
        this_item = input_points[0]
        for item in input_points[1:]:
            prev_item = this_item
            this_item = item
            coord_dist = distance(prev_item, this_item)
            dist.append(coord_dist)
        return sum(dist)
    

    【讨论】:

      猜你喜欢
      • 2020-05-31
      • 2013-03-02
      • 2011-01-29
      • 2015-07-15
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多