2014-12-02 184 views
3

比方说,我们有两个相等长度的数组:Python:如何在两个单独的数组之间找到两个相等/最接近的值?

arr1 = (21, 2, 3, 5, 13) 
arr2 = (10, 4.5, 9, 12, 20) 

哪个变量从arr1等于/最接近arr2一个变量?

看看这两个清单,我们可以很容易地说最接近的数字是4.5和。我试着实现一个函数,返回两个最接近的值给出两个列表,它有点工作上面的例子,但它只是一个解决方案,因为它不是最佳的。你可以很容易地检查功能,当我们稍微改变这样的阵列失败:

arr1 = (21, 2, 3, 5, 13) 
arr2 = (10, 4.5, 9, 12, 18) 

函数返回13值和18

下面是函数:

def get_nearest(arr1, arr2): 
    lr = [[0, 0, 0]] 
    for x1 in arr1: 
     for x2 in arr2: 
      r = (x1/x2 % (x1 + x2)) 
      print x1, x2, r 
      if r <= 1 and r >= lr[0][2]: 
       lr.pop() 
       lr.append([x1, x2, r]) 
    return lr 

你能想出一个更好的吗?

+1

对我来说它似乎是5和4.5最接近? – 2014-12-02 00:19:43

+0

你是对的,我的错误 – minerals 2014-12-02 00:20:35

回答

3

速度问题?你关心领带吗?如果不是,约像

from itertools import product 
sorted(product(arr1, arr2), key=lambda t: abs(t[0]-t[1]))[0] 

简单的东西对于这两种

arr1 = (21, 2, 3, 5, 13) 
arr2 = (10, 4.5, 9, 12, 20) 

arr1 = (21, 2, 3, 5, 13) 
arr2 = (10, 4.5, 9, 12, 18) 

这会产生什么

(5, 4.5) 

说明:

product(arr1, arr2) = [(a1, a2) for (a1, a2) in product(arr1, arr2)] 

得到所有N**2双号码的列表:

[(21, 10), (21, 4.5), ..., (13, 12), (13, 20)] 

然后,我们通过使用sorted的绝对差值(|a1 - a2|)对其进行排序。通过传递sorted关键字key,我们告诉sorted使用排序标准lambda t: abs(t[0] - t[1])。具有最小绝对差异的对被放置在排序数组的第一个索引中,因此我们可以通过在末尾加上[0]来抓取它。

编辑:

正如意见建议的彼得,你可以养活一个key=funcminmax,这大大加快了这一最高。尝试改为:

from itertools import product 
min(product(arr1, arr2), key=lambda t: abs(t[0]-t[1]))[0] 
+0

确实不错,但我需要一些时间来了解这里发生了什么。 – minerals 2014-12-02 00:29:44

+0

@矿物质,我补充说明。 – wflynny 2014-12-02 00:39:48

+1

您应该使用max而不是sorted()[0] – 2014-12-05 23:03:09

1
>>> arr1 = (21, 2, 3, 5, 13) 
>>> arr2 = (10, 4.5, 9, 12, 20) 
>>> for a1 in arr1: 
...  for a2 in arr2: 
...   if a1 > a2: 
...    result.append([a1, a2, a1-a2]) 
...   else: 
...    result.append([a1, a2, a2-a1]) 
>>> sorted(result, key=lambda i:i[-1])[0][:2] 
[5, 4.5] 

一个简单的方法可以两个阵列之间获得差异,并通过他们的差异对它们进行排序并获得第一个元素。

>>> sorted([[a1,a2,a1-a2] if(a1>a2) else [a1,a2,a2-a1] for a1 in arr1 for a2 in arr2], key=lambda i:i[-1])[0][:2] 
[5, 4.5] 
1

什么简单的储蓄的差异,在每次迭代中值...

arr1 = (21, 2, 3, 5, 13) 
arr2 = (10, 4.5, 9, 12, 20) 

diff = float("inf") 

for a1 in arr1: 
    for a2 in arr2: 
     if abs(a1-a2) < diff: 
      diff = abs(a1-a2) 
      values = (a1, a2) 

print(values) 
3

这是最快的算法,我能写,它具有的n * log(n)的复杂性,这种比其他答案中提出的天真n * n方法快得多。它处理(它是最耗时的部分)之前排序阵列和稍后尝试最小化的差异(这需要在最坏情况下2 * N):

def closest_array_items(a1, a2): 
    if not a1 or not a2: 
     raise ValueError('Empty array') 
    a1, a2 = iter(sorted(a1)), iter(sorted(a2)) 
    i1, i2 = a1.next(), a2.next() 
    min_dif = float('inf') 
    while 1: 
     dif = abs(i1 - i2) 
     if dif < min_dif: 
      min_dif = dif 
      pair = i1, i2 
      if not min_dif: 
        break 
     if i1 > i2: 
      try: 
       i2 = a2.next() 
      except StopIteration: 
       break 
     else: 
      try: 
       i1 = a1.next() 
      except StopIteration: 
       break 
    return pair 
1

在这里,其在解决该问题的功能〜0.01 s为长度为1000,2000的两个向量:

def get_closest_elements(arr_1, arr_2): 
    """ 
    The function finds the two closest elements in two arrays 

    Returns 
    ------- 
    idx_1 : int 
     index of element in arr_1 
    idx_2 : int 
     index of element in arr_2 
    min_diff : float 
     minimal difference between arrays 
    """ 

    # get array with all differences between arrays 
    diff_arr = x[:, np.newaxis] - y 

    # get absolute value 
    diff_arr = np.abs(diff_arr) 

    # get minimum difference 
    min_diff = np.min(diff_arr) 

    # get the indexes for the elements of interest in arr_1 and arr_2 
    idx_1, idx_2 = np.where(diff_arr == min_diff) 

    return idx_1, idx_2, min_diff 


# apply function 
x = np.array([21, 2, 3, 5, 13]) 
y = np.array([10, 4.5, 9, 12, 20]) 
# n = 1000 
# x = np.random.rand(n) 
# y = np.random.rand(2*n) 

idx_1, idx_2, min_diff = get_closest_elements(x, y) 
print "x{} - y{} = {}".format(idx_1, idx_2, min_diff) 
相关问题