【问题标题】:Python: For each list element apply a function across the listPython:对于每个列表元素,在列表中应用一个函数
【发布时间】:2010-10-04 08:23:00
【问题描述】:

鉴于[1,2,3,4,5],我该怎么做类似的事情

1/1, 1/2, 1/3,1/4,1/5, ...., 3/1,3/2,3/3,3/4,3/5,.... 5/1,5/2,5/3,5/4,5/5

我想存储所有结果,找到最小值,然后返回用于查找最小值的两个数字。所以在我上面描述的情况下,我想返回(1,5)

所以基本上我想做类似的事情

对于列表中的每个元素i 将某个函数映射到列表中的所有元素,以 ij 作为参数 将结果存储在主列表中,在主列表中找到最小值,并返回参数ij用于计算这个最小值。

在我真正的问题中,我有一个对象/坐标列表,我使用的函数需要两个坐标并计算欧几里得距离。我试图找到任意两点之间的最小欧几里得距离,但我不需要花哨的算法。

【问题讨论】:

    标签: python algorithm list list-comprehension


    【解决方案1】:

    您可以使用list comprehensionsmin()(Python 3.0 代码)来做到这一点:

    >>> nums = [1,2,3,4,5]
    >>> [(x,y) for x in nums for y in nums]
    [(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]
    >>> min(_, key=lambda pair: pair[0]/pair[1])
    (1, 5)
    

    请注意,要在 Python 2.5 上运行此程序,您需要将其中一个参数设为浮点数,或执行 from __future__ import division 以使 1/5 正确地等于 0.2 而不是 0。

    【讨论】:

    • 请注意,min 的 'key' 参数仅在 2.5 之后才被接受
    • 我会使用 zip(nums, nums) 而不是 listcomp,否则这将是我的解决方案。
    • 其实 zip(nums, nums) 的结果是 [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],这是不正确的。
    • 为了更好地利用内存,可以使用生成器代替列表:nums = [1, 2, 3, 4, 5] pairs = ((x, y) for x in nums for y in nums) m = min(pairs, key=lambda pair: pair[0] / pair[1]) 因此,每对都是按顺序生成的,这比保留对列表更节省内存。跨度>
    • 对于那些想知道发布代码中的单个下划线的人:What is the purpose of the single underscore “_” variable in Python?
    【解决方案2】:

    如果我认为您想为列表中所有可能的 2 个元素对找到函数的最小值是正确的...

    l = [1,2,3,4,5]
    
    def f(i,j):
       return i+j 
    
    # Prints min value of f(i,j) along with i and j
    print min( (f(i,j),i,j) for i in l for j in l)
    

    【讨论】:

    • 名为“l”的列表让我有点害怕。不过很好的解决方案:)
    • 是的,我总是称我的通用列表为“lst”。
    • 我会在末尾添加一个 [1:]: print min( (1.*i/j,i,j) for i in l for j in l)[1:]
    • 想了一下,但我觉得它的可读性要差得多@Andrea
    • @Triptych: 1.*i/j 还是 [1:] ?!?
    【解决方案3】:

    一些可读的python:

    def JoeCalimar(l):
        masterList = []
        for i in l:
            for j in l:
                masterList.append(1.*i/j)
        pos = masterList.index(min(masterList))
        a = pos/len(masterList)
        b = pos%len(masterList)
        return (l[a],l[b])
    

    如果有什么不清楚的地方请告诉我。

    【讨论】:

      【解决方案4】:

      如果您不介意导入 numpy 包,它内置了许多方便的功能。使用它们的数据结构可能比使用列表等更有效。

      from __future__ import division
      
      import numpy
      
      data = numpy.asarray([1,2,3,4,5])
      dists = data.reshape((1,5)) / data.reshape((5,1))
      
      print dists
      
      which = dists.argmin()
      (r,c) = (which // 5, which % 5) # assumes C ordering
      
      # pick whichever is most appropriate for you...
      minval = dists[r,c]
      minval = dists.min()
      minval = dists.ravel()[which]
      

      【讨论】:

        【解决方案5】:

        用数学的方式来做......

        nums = [1, 2, 3, 4, 5]
        min_combo = (min(nums), max(nums))
        

        当然,除非你有底片。在这种情况下,这将不起作用,因为您实际上想要最小和最大绝对值 - 分子应该接近于零,而分母应该远离它,在任一方向上。双重否定会破坏它。

        【讨论】:

        • 顺便说一句,不做问题所要求的。是的,它是问题中简单示例的解决方案,但它没有说明如何将某些函数应用于数字对。 (或者也许这个答案发布后问题得到了改善。)
        【解决方案6】:

        如果使用 Python ≥2.6(包括 3.x),您可以:

        from __future__ import division
        import operator, itertools
        
        def getmin(alist):
            return min(
                (operator.div(*pair), pair)
                for pair in itertools.product(alist, repeat=2)
            )[1]
        
        getmin([1, 2, 3, 4, 5])
        

        编辑:现在我想起来了,如果我没记错我的数学,这也应该给出假设所有数字都是非负数的答案:

        def getmin(alist):
            return min(alist), max(alist)
        

        【讨论】:

        • 如果 OP 想要计算欧几里得距离,有 itertools.combinations 生成器,它只会从输入中产生唯一的不同值对。
        • @liori:OP 似乎不想要欧几里得距离。无论如何,感谢您的评论,因为它让我想起了这个问题。
        【解决方案7】:
        >>> nums = [1, 2, 3, 4, 5]    
        >>> min(map((lambda t: ((float(t[0])/t[1]), t)), ((x, y) for x in nums for y in nums)))[1]
        (1, 5)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-09
          • 1970-01-01
          • 2014-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多