【问题标题】:Python: How to find two equal/closest values between two separate arrays?Python:如何在两个单独的数组之间找到两个相等/最接近的值?
【发布时间】:2014-12-02 00:17:53
【问题描述】:

假设我们有两个长度相等的数组:

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

arr1 中的哪个变量与arr2 中的变量相等/最接近

查看这两个列表,我们可以轻松地说最接近的数字是 4.55。我尝试实现一个函数,该函数在给定两个列表的情况下返回两个最接近的值,对于上面的示例,它有点工作,但它几乎不是一个解决方案,因为它不是最优的。当我们像这样稍微更改数组时,您可以轻松检查函数是否失败:

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

你能想出一个更好的吗?

【问题讨论】:

  • 对我来说似乎 5 和 4.5 最接近?
  • 你是对的,我的错

标签: python comparison


【解决方案1】:

速度有问题吗?你在乎关系吗?如果没有,那么简单的东西呢

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] 来抓取它。

编辑:

按照 Piotr 在 cmets 中的建议,您可以将 key=func 输入到 minmax,这大大加快了速度。试试吧:

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

【讨论】:

  • 确实不错,但我需要一些时间来了解这里发生了什么。
  • @minerals,我添加了解释。
  • 你应该使用 max 而不是 sorted()[0]
【解决方案2】:

这是我能够编写的最快的算法,它具有 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

【讨论】:

    【解决方案3】:
    >>> 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]
    

    【讨论】:

      【解决方案4】:

      在每次迭代中简单地保存差异和值怎么样...

      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)
      

      【讨论】:

        【解决方案5】:

        对于长度为 1000、2000 的两个向量,这里有一个函数可以在 ~0.01 秒内解决这个问题:

        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)
        

        【讨论】:

          猜你喜欢
          • 2016-03-03
          • 1970-01-01
          • 1970-01-01
          • 2016-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-16
          相关资源
          最近更新 更多