我需要创建一个我创建的列表并找到最接近的两个点并打印出来。如何比较列表中的每个点?
没有任何需要绘制或任何东西,只需比较点并找到列表中最接近的两个。
import math # 'math' needed for 'sqrt'
# Distance function
def distance(xi,xii,yi,yii):
sq1 = (xi-xii)*(xi-xii)
sq2 = (yi-yii)*(yi-yii)
return math.sqrt(sq1 + sq2)
# Run through input and reorder in [(x, y), (x,y) ...] format
oInput = ["9.5 7.5", "10.2 19.1", "9.7 10.2"] # Original input list (entered by spacing the two points).
mInput = [] # Manipulated list
fList = [] # Final list
for o in oInput:
mInput = o.split()
x,y = float(mInput[0]), float(mInput[1])
fList += [(x, y)] # outputs [(9.5, 7.5), (10.2, 19.1), (9.7, 10.2)]
答案 0 :(得分:34)
重写distance()
函数以将两个(x, y)
元组作为参数更方便:
def distance(p0, p1):
return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
现在您要迭代列表fList
中的所有点对。函数iterools.combinations()
用于此目的很方便:
min_distance = distance(fList[0], fList[1])
for p0, p1 in itertools.combinations(fList, 2):
min_distance = min(min_distance, distance(p0, p1))
另一种方法是定义distance()
以接受单个参数中的点对
def distance(points):
p0, p1 = points
return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
并将key
参数用于内置min()
函数:
min_pair = min(itertools.combinations(fList, 2), key=distance)
min_distance = distance(min_pair)
答案 1 :(得分:11)
我意识到这个问题存在库约束,但是为了完整性,如果你在Nx2 numpy ndarray(2D系统)中有N
个点:
from scipy.spatial.distance import pdist
x = numpy.array([[9.5,7.5],[10.2,19.1],[9.7,10.2]])
mindist = numpy.min(pdist(x))
我总是试图鼓励人们使用numpy / scipy,如果他们正在处理最好存储在数值数组中的数据,并且很高兴知道这些工具可以在那里供将来参考。
答案 2 :(得分:2)
请注意math.sqrt
函数速度很慢,在这种情况下是不必要的。尝试比较平方距离以加快速度(排序距离与距离平方将始终产生相同的排序):
def distSquared(p0, p1):
return (p0[0] - p1[0])**2 + (p0[1] - p1[1])**2
答案 3 :(得分:2)
您的固定代码。没有有效的算法,只有蛮力的算法。
import math # math needed for sqrt
# distance function
def dist(p1, p2):
return math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2)
# run through input and reorder in [(x, y), (x,y) ...] format
input = ["9.5 7.5", "10.2 19.1", "9.7 10.2"] # original input list (entered by spacing the two points)
points = [map(float, point.split()) for point in input] # final list
# http://en.wikipedia.org/wiki/Closest_pair_of_points
mindist = float("inf")
for p1, p2 in itertools.combinations(points, 2):
if dist(p1, p2) < mindist:
mindist = dist(p1, p2)
closestpair = (p1, p2)
print(closestpair)
答案 4 :(得分:1)
这可能有效:
oInput = ["9.5 7.5", "10.2 19.1", "9.7 10.2"]
# parse inputs
inp = [(float(j[0]), float(j[1])) for j in [i.split() for i in oInput]]
# initialize results with a really large value
min_distance = float('infinity')
min_pair = None
# loop over inputs
length = len(inp)
for i in xrange(length):
for j in xrange(i+1, length):
point1 = inp[i]
point2 = inp[j]
if math.hypot(point1[0] - point2[0], point1[1] - point2[0]) < min_distance:
min_pair = [point1, point2]
一旦完成循环,min_pair应该是距离最小的一对。
使用float()来解析文本会留下改进的空间。
math.hypot比计算手写python函数中的距离快大约三分之一答案 5 :(得分:0)
首先,一些注意事项:
a**2 # squares a
(xi - xii)**2 # squares the expression in parentheses.
mInput不需要提前申报
fList.append((x, y))
比使用+=
更加pythonic。
现在你有fList
。您的距离函数可以被重写为2个2元组(点)参数,我不会在这里打扰。
然后你可以写:
shortest = float('inf')
for pair in itertools.combinations(fList, 2):
shortest = min(shortest, distance(*pair))
答案 6 :(得分:0)
以上许多问题建议使用math.sqrt
查找平方根,这很慢,而且不是查找平方根的好方法。尽管使用了这种方法,但只要回想一下学校的基本概念即可:考虑取任何正数x的平方根。然后将平方根写为二分之一的幂:x1 / 2。因此,分数指数表示要取某根。
所以不要使用math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
使用
def distance(a,b):
euclidean_distance = ((b[0]-a[0])**2 + (a[1]-a[1])**2)**0.5
return(euclidean_distance)
希望有帮助