【问题标题】:Python "round robin"Python“循环赛”
【发布时间】:2009-04-08 04:38:53
【问题描述】:

给定多个 (x,y) 有序对,我想比较它们之间的距离。 所以假设我有一个有序对的列表:

pairs = [a,b,c,d,e,f]

我有一个函数,它接受两个有序对并找到它们之间的距离:

def distance(a,b):
    from math import sqrt as sqrt
    from math import pow as pow
    d1 = pow((a[0] - b[0]),2)
    d2 = pow((a[1] - b[1]),2)
    distance = sqrt(d1 + d2)
    return distance

如何使用此函数将每个有序对与其他每个有序对进行比较,最终找到它们之间距离最大的两个有序对?

伪代码:

     distance(a,b)
     distance(a,c)
     ...
     distance(e,f)

任何帮助将不胜感激。

【问题讨论】:

  • “from math import sqrt as sqrt”与“from math import sqrt”完全相同。前者就像说“嗨,我叫罗伯托,但请叫我罗伯托”:)
  • 也可以省略数学模块,使用** 0.5
  • 我怀疑你真的想要无序对,因为你的距离函数是对称的..
  • @John:听起来不错。此外,他的示例在距离(e,f)处停止——如果他想要有序对,最后一个将是距离(f,e)。
  • 一个小提示:如果您不关心实际距离是多少(只是它们是相距最远的两对),您可以消除平方根以加快速度。平方是单调的,并且对于大于或等于 0 的值增加。即 x > y 当且仅当 xx > yy 对于 x, y >= 0。

标签: python iteration round-robin


【解决方案1】:

在 python 2.6 中,您可以使用 itertools.permutations

import itertools
perms = itertools.permutations(pairs, 2)
distances = (distance(*p) for p in perms)

import itertools
combs = itertools.combinations(pairs, 2)
distances = (distance(*c) for c in combs)

【讨论】:

  • 组合可能会更好,因为 A->B 和 B->A 的距离相同。
  • 您对 2 个不同的事物使用相同的术语。可能想选择一个更好的变量名。 “对”似乎是“对”中的一项,但实际上不是。
【解决方案2】:
try:

    from itertools import combinations

except ImportError:

    def combinations(l, n):
        if n != 2: raise Exception('This placeholder only good for n=2')
        for i in range(len(l)):
            for j in range(i+1, len(l)):
                yield l[i], l[j]


coords_list = [(0,0), (3,4), (6,8)]

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

largest_distance, (p1, p2) = max([
     (distance(p1,p2), (p1, p2)) for (p1,p2) in combinations(coords_list, 2)
     ])


print largest_distance, p1, p2

【讨论】:

  • 不需要itertools的答案怎么了?我回到这个页面,它消失了! :(
【解决方案3】:

试试:

max(distance(a, b) for (i, a) in enumerate(pairs) for b in pairs[i+1:])

这避免了身份比较(例如distance(x, x)distance(y, y) 等)。它还避免进行对称比较,因为distance(x, y) == distance(y, x)


更新:我喜欢 Evgeny's solution 更好地使用itertools,因为它更简洁地表达了你想要做的事情。我们的两种解决方案都做同样的事情。 (注意:确保你使用combinations,而不是permutations——那会慢得多!)

【讨论】:

  • 这是一个优雅的解决方案,但有一个可能的缺点:为每个元素复制一次列表的成本可能很高。
【解决方案4】:

有点相关,你不必自己计算欧几里得距离,还有 math.hypot:

In [1]: a = (1, 2)
In [2]: b = (4, 5)
In [3]: hypot(a[0]-b[0], a[1]-b[1])
Out[3]: 4.2426406871192848

【讨论】:

    【解决方案5】:

    如果您不介意在两次相同的两点之间进行距离计算,以下将找到最大距离:

    max( [distance(a, b) for a in pairs for b in pairs] )
    

    要改为使用 a 和 b 对,请执行以下操作:

    import operator
    max( [((a,b), distance(a, b)) for a in pairs for b in pairs], key=operator.itemgetter(1))
    

    您可以将其与 John Feminella 的解决方案相结合,以获得 (a,b) 元组,而无需进行过多的距离比较

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 2019-10-03
      • 2022-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多