[英]Given two lists of 2d points, how to find the closest point in the 2nd list for every point in the 1st list?
[英]Find the closest and the farthest points (2D) between a given point and a list of points in python
所以我正在尝试编写一个 python 函数,它可以将任何给定点说(1,2)我们可以称之为兴趣点,然后获取点列表说[(6,2), (4,5), (3,4),...]函数应该返回离我们的兴趣点最近和最远的点(从列表中)。
该函数应接受两个参数:
1. Point of interest i.e. pos=(1,2)
2. List of points i.e. ptlist=[(1,3),(6,2), (4,5), (3,4)]
该函数还应该以 ((1,3),(4,5)) 的形式返回答案,即(最近的,最远的)
这是我的代码,到目前为止它有效,但它返回 numpy 数组,而我希望我的答案是元组。 我尝试了不同的方法,无论我尝试什么,我似乎都无法做到。 也许我们可以使用除 numpy 之外的其他东西,以便我们以 ((1,3),(4,5)) 的形式获得答案。
这是我到目前为止编写的代码:
pos=(1,2)
ptlist=[(2, 6), (8,6), (5,8), (2,4)]
def get_nearest_farthest(pt, ptlist):
pt=np.array(pt)
ptlist=np.array(ptlist)
dist=np.linalg.norm(ptlist-pt, axis=1)
min_index = np.argmin(dist)
#tuple(map(tuple,ptlist[min_index])) #Error
max_index = np.argmax(dist)
#tuple(map(tuple,ptlist[max_index])) #Error
return ptlist[min_index],ptlist[max_index]
get_nearest_farthest(pt, ptlist)
你不需要numpy
。 您只需要带有key
参数的min()
/ max()
:
distance_metric = lambda x: (x[0] - pos[0])**2 + (x[1] - pos[1])**2
closest = min(ptlist, key=distance_metric)
farthest = max(ptlist, key=distance_metric)
print(closest, farthest)
这输出:
(2, 4) (8, 6)
这将在不使用 numpy 的情况下到达那里,并且非常有效,只需对列表中的每个点进行一次距离计算。
def get_nearest_farthest(pos, pt_list):
nearest_pt, farthest_pt = None, None
nearest_d, farthest_d = None, None
for pt in pt_list:
d = (pos[0]-pt[0])**2 + (pos[1]-pt[1])**2
if nearest_d is None or d < nearest_d:
nearest_d = d
nearest_pt = pt
if farthest_d is None or d > farthest_d:
farthest_d = d
farthest_pt = pt
return nearest_pt, farthest_pt
pos = (1,2)
pt_list = [(2, 6), (8,6), (5,8), (2,4)]
get_nearest_farthest(pos, pt_list)
有许多方法可以解决这个问题。 你的就是其中之一,要以元组的形式获得结果,将结果数组转换回list
就足够了,并结合使用tuple()
和np.ndarray.tolist()
。
就最快的执行而言,这一切都归结为输入的大小。
在这里,我提供了一些实现(一些类似于其他答案)以及一些时间:
import numpy as np
def p_dist_np(x, y, p=2):
if p % 2:
return np.sum(np.abs(x - y) ** p, axis=-1)
else:
return np.sum((x - y) ** p, axis=-1)
def minmax_dist_np(x0, xs, d_func=p_dist_np):
x0 = np.array(x0)
xs = np.array(xs)
dists = d_func(x0, xs)
min_i = np.argmin(dists)
max_i = np.argmax(dists)
return tuple(xs[min_i].tolist()), tuple(xs[max_i].tolist())
import numpy as np
import numba as nb
@nb.njit
def p_dist_nb(x, y, p=2):
if p % 2:
return np.sum(np.abs(x - y) ** p)
else:
return np.sum((x - y) ** p)
@nb.njit
def _minmax_dist_nb(x0, xs, d_func=p_dist_nb):
min_i = max_i = 0
min_d = max_d = d_func(x0, xs[min_i])
for i, x in enumerate(xs[1:], 1):
d = d_func(x0, x)
if d < min_d:
min_d = d
min_i = i
elif d > max_d:
max_d = d
max_i = i
return min_i, max_i
def minmax_dist_nb(x0, xs, d_func=p_dist_nb):
x0 = np.array(x0)
xs = np.array(xs)
min_i, max_i = _minmax_dist_nb(x0, xs, d_func=d_func)
return tuple(xs[min_i].tolist()), tuple(xs[max_i].tolist())
def p_dist(x, y, p=2):
if p % 2:
return sum(abs(x_i - y_i) ** p for x_i, y_i in zip(x, y))
else:
return sum((x_i - y_i) ** p for x_i, y_i in zip(x, y))
def minmax_dist_loop(x0, xs, d_func=p_dist):
i_xs = iter(xs)
min_i = max_i = 0
min_d = max_d = d_func(x0, next(i_xs))
for i, x in enumerate(i_xs, 1):
d = d_func(x0, x)
if d < min_d:
min_d = d
min_i = i
elif d > max_d:
max_d = d
max_i = i
return xs[min_i], xs[max_i]
def minmax_dist_key(x0, xs, d_func=p_dist):
return (
min(xs, key=lambda x: d_func(x, x0)),
max(xs, key=lambda x: d_func(x, x0)))
以及获取时间的代码:
x0 = (1, 2)
xs = [(2, 6), (8, 6), (5, 8), (2, 4)]
funcs = minmax_dist_np, minmax_dist_loop, minmax_dist_key, minmax_dist_nb
for n in (1, 10, 100, 1000):
nxs = xs * n
print(f"N = {n * len(xs)}")
base = funcs[0](x0, nxs)
for func in funcs:
res = func(x0, nxs)
print(f"{func.__name__:>24} {base == res}", end=' ')
%timeit -n 50 func(x0, nxs)
# N = 4
# minmax_dist_np True 50 loops, best of 5: 16.2 µs per loop
# minmax_dist_loop True 50 loops, best of 5: 6.11 µs per loop
# minmax_dist_key True 50 loops, best of 5: 11.6 µs per loop
# minmax_dist_nb True 50 loops, best of 5: 18.1 µs per loop
# N = 40
# minmax_dist_np True 50 loops, best of 5: 39.6 µs per loop
# minmax_dist_loop True 50 loops, best of 5: 54.3 µs per loop
# minmax_dist_key True 50 loops, best of 5: 107 µs per loop
# minmax_dist_nb True 50 loops, best of 5: 43.2 µs per loop
# N = 400
# minmax_dist_np True 50 loops, best of 5: 232 µs per loop
# minmax_dist_loop True 50 loops, best of 5: 550 µs per loop
# minmax_dist_key True 50 loops, best of 5: 1.07 ms per loop
# minmax_dist_nb True 50 loops, best of 5: 281 µs per loop
# N = 4000
# minmax_dist_np True 50 loops, best of 5: 2.28 ms per loop
# minmax_dist_loop True 50 loops, best of 5: 5.7 ms per loop
# minmax_dist_key True 50 loops, best of 5: 11.3 ms per loop
# minmax_dist_nb True 50 loops, best of 5: 2.78 ms per loop
表明对于足够小的输入, minmax_dist_loop()
是最快的,但是一旦输入变大, minmax_dist_np()
和minmax_dist_nb()
以相当大的优势接管。 相反, minmax_dist_key()
逐渐变得最慢,主要是因为它需要计算两倍于minmax_dist_loop()
的昂贵距离函数。 虽然对于minmax_dist_np()
也计算了两次循环,但距离的计算只进行了一次(以创建可能很大的临时对象为代价)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.