【问题标题】:finding n largest differences between two lists找到两个列表之间的 n 个最大差异
【发布时间】:2012-03-08 13:15:19
【问题描述】:

我有两个列表 oldnew,元素数量相同。

我正在尝试编写一个以n 为参数的高效函数,比较相同位置的两个列表的元素(按索引),找到n 的最大差异,并返回那些@ 的索引987654326@ 元素。

我认为这最好通过按值排序的字典来解决,但在 Python 中有一个 isn't available(我不知道有任何库提供它)。也许有更好的解决方案?

【问题讨论】:

    标签: python algorithm data-structures ordereddictionary


    【解决方案1】:

    每当您想到“n largest”时,就想到heapq

    >>> import heapq
    >>> import random
    >>> l1 = [random.randrange(100) for _ in range(100)]
    >>> l2 = [random.randrange(100) for _ in range(100)]
    >>> heapq.nlargest(10, (((a - b), a, b) for a, b in zip(l1, l2)))
    [(78, 99, 21), (75, 86, 11), (69, 90, 21), (69, 70, 1), (60, 86, 26), (55, 95, 40), (52, 56, 4), (48, 98, 50), (46, 80, 34), (44, 81, 37)]
    

    这将在 O(n log x) 时间内找到 x 个最大的项目,其中 n 是列表中的项目总数;排序在 O(n log n) 时间内完成。

    我突然想到,上述内容实际上并没有满足您的要求。你想要一个索引!还是很容易的。如果你想要差的绝对值,我也会在这里使用abs

    >>> heapq.nlargest(10, xrange(len(l1)), key=lambda i: abs(l1[i] - l2[i]))
    [91, 3, 14, 27, 46, 67, 59, 39, 65, 36]
    

    【讨论】:

      【解决方案2】:

      这是numpy 中的一个解决方案(免责声明,我是 numpy 的新手,所以可能有更巧妙的方法来做到这一点)。我没有结合任何步骤,所以很清楚每个步骤在做什么。最终值是原始列表的索引列表,按增量最高的顺序排列。选择顶部的 n 很简单,sorted_inds[:n] 并从每个列表或增量列表中检索值是微不足道的。

      我不知道它与其他解决方案的性能相比如何,而且它显然不会出现在如此小的数据集上,但它可能值得用你的真实数据集进行测试,因为我的理解是 numpy 是数值数组运算非常非常快。

      代码

      import numpy
      
      list1 = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
      list2 = numpy.array([9, 8, 7, 6, 5, 4, 3, 2, 1])
      
      #Caculate the delta between the two lists
      delta = numpy.abs(numpy.subtract(list1, list2))
      print('Delta: '.ljust(20) + str(delta))
      
      #Get a list of the indexes of the sorted order delta
      sorted_ind = numpy.argsort(delta)
      print('Sorted indexes: '.ljust(20) + str(sorted_ind))
      
      #reverse sort
      sorted_ind = sorted_ind[::-1]
      print('Reverse sort: '.ljust(20) + str(sorted_ind))
      

      输出

      Delta:              [8 6 4 2 0 2 4 6 8]
      Sorted indexes:     [4 3 5 2 6 1 7 0 8]
      Reverse sort:       [8 0 7 1 6 2 5 3 4]
      

      【讨论】:

        【解决方案3】:
        >>> l = []
        ... for i in itertools.starmap(lambda x, y: abs(x-y), itertools.izip([1,2,3],   [100,102,330])):
        ...     l.append(i)
        >>> l
        5: [99, 100, 327]
        

        itertools 可用于重复性任务。从starmaptuples 转换为*args。对于referenceWith max 函数你将能够得到想要的结果。 index 函数将帮助找到位置。

        l.index(max(l)

        >>> l.index(max(l))
        6: 2
        

        【讨论】:

          【解决方案4】:

          根据您的问题,我认为这就是您想要的:

          区别.py

          l1 = [15,2,123,4,50]
          l2 = [9,8,7,6,5]
          
          
          l3 = zip(l1, l2)
          
          def f(n):
              diff_val = 0
              index_val = 0
              l4 = l3[:n]
          
              for x,y in l4:
                  if diff_val < abs(x-y):
                      diff_val = abs(x-y)
                      elem = (x, y)
                      index_val = l3.index(elem)
          
              print "largest diff: ", diff_val
              print "index of values:", index_val
          
          
          n = input("Enter value of n:") 
          
          f(n)
          

          执行:

          [avasal@avasal ]# python difference.py 
          Enter value of n:4
          largest diff:  116
          index of values: 2
          [avasal@avasal]#
          

          如果这不是您想要的,请考虑再详细说明问题..

          【讨论】:

            【解决方案5】:

            假设列表中的元素数量不多,您可以将它们全部区分,排序并选择第一个n

            print sorted((abs(x-y) for x,y in zip(old, new)), reverse=True)[:n]
            

            这将是O(k log k),其中k 是您的原始列表的长度。

            如果n 明显小于k,最好的办法是使用nlargest 模块提供的nlargest 函数:

            import heapq
            print heapq.nlargest(n, (abs(x-y) for x,y in zip(old, new))
            

            这将是O(k log n),而不是O(k log k),这对k &gt;&gt; n 可能很重要。 此外,如果您的列表非常大,您最好使用itertools.izip 而不是常规的zip 函数。

            【讨论】:

              猜你喜欢
              • 2017-04-18
              • 1970-01-01
              • 1970-01-01
              • 2013-03-27
              • 2013-01-02
              • 2015-03-19
              • 2019-11-23
              • 2016-07-04
              • 1970-01-01
              相关资源
              最近更新 更多