假设我有points
形式的元组列表(x, y)
,其x
和y
个浮点数。检查点(v,w)
是否接近(欧几里德距离小于某个epsilon)到points
中的某个点的最pythonic方法是什么?
(当然,天真的方式是用for循环看。)
我主要想知道python 3,但作为参考,python 2的答案也很好。使用开源库的答案也是可以接受的。
答案 0 :(得分:1)
就个人而言,我会这样做:
#given GIVEN_POINT, MAX_DISTANCE and POINTS
from math import sqrt
print(list(map(lambda e: e[0],filter(lambda x: x[1]<=MAX_DISTANCE, map(lambda p: (p,sqrt((p[0]-GIVEN_POINT[0])**2+(p[1]-GIVEN_POINT[1])**2)),POINTS)))))
说明:
from math import sqrt
#given GIVEN_POINT, MAX_DISTANCE and POINTS
distance=lambda p: sqrt((p[0]-GIVEN_POINT[0])**2+(p[1]-GIVEN_POINT[1])**2)
#(the Euclidean distance from p to GIVEN_POINT where P is a point like (x,y))
point_distance = lambda p: (p,distance(p))
#map store the distance along with each point
points_n_distances = map(point_distance,POINTS)
#Now we have something like [((x1,y1),d1),((x2,y2),d2)...] in a map
close = lambda p: p[1]<=MAX_DISTANCE
closer_points = filter(close,points_n_distances)
#We do a filter based on the distances
to_point = lambda p: p[0]
filtered=map(to_point,closer_points)
#we remove the extra bit of data
#now filtered contains all the (x,y) points which are maximum of a MAX_DISTANCE far from GIVEN_POINT
不要忘记filtered
仍然是map
!
答案 1 :(得分:1)
一个简单的for循环清楚地显示了意图,甚至更弱的程序员也可以看到你在做什么,隐藏更复杂的语言结构背后的逻辑是不正确的方式
当然,当你决定改变距离的计算方式/你可能希望在代码中的其他地方使用距离函数时,for循环应该在某个函数中以及距离计算 另外,当你只是寻找最近的点时,你不需要有距离 - 平方距离更容易计算
def distance_squared(point_from, point_to):
return (point_from[0] - point_to[0]) ** 2 + (point_from[1] - point_to[1]) ** 2
def contains(points, target_point, threshold):
threshold_squared = threshold ** 2
for point in points:
if distance_squared(target_point, point) <= threshold_squared:
return True
return False
my_points = [(1, 2), (3, 4), (5.2, 6.3), (7.4, 8.5), (9.6, 10.7), (11.8, 12.9)]
print(contains(my_points,(1,1),0)) # False
print(contains(my_points,(1,1),1)) # True
print(contains(my_points,(3,4),0)) # True
你要求点是浮点元组的事实限制了外部库的使用,如numpy或scipy
查看此代码查看问题https://codereview.stackexchange.com/questions/28207/finding-the-closest-point-to-a-list-of-points以查看一个numpy解决方案 - 它看起来更干净,运行速度更快,但限制您使用numpy数组
答案 2 :(得分:0)
以下是numpy
的一种方式,但效率不高。
import numpy as np
lst = [(2, 1.5), (5, 1.6), (3.2, 4), (1, 0.9), (6.2, 3), (0.999, 0.901)]
def isclose_lst(x, arrs, tolerance=0.01):
return [i for i in arrs if np.all(np.isclose(np.array((x[0], x[1])),\
np.array((i[0], i[1])), atol=tolerance))]
isclose_lst((1.001, 0.899), lst)
# [(1, 0.9), (0.999, 0.901)]