【问题标题】:sum of products for multiple lists in pythonpython中多个列表的产品总和
【发布时间】:2011-04-20 10:33:08
【问题描述】:

试图模仿 Excel 的 SUMPRODUCT 函数:

SUMPRODUCT(v1, v2, ..., vN) =
    v1[0]*v2[0]*...*vN[0] + v1[1]*v2[1]*...*vN[1] + ... + v1[n]*v2[n]*...*vN[n]

其中 n 是每个向量中的元素数。

这类似于点积,但适用于多个向量。我阅读了常规点积的the very detailed discussion,但我不知道如何干净地将其扩展到多个向量。作为参考,我正在复制那里提出的优化代码,我将其(微不足道地)移植到 Python 3。顺便说一句,对于点积,最后一种方法仍然在 P3K 中获胜。

def d0(v1,v2):
    """                                                                                                     
    d0 is Nominal approach:                                                                                 
    multiply/add in a loop                                                                                  
    """
    out = 0
    for k in range(len(v1)):
        out += v1[k] * v2[k]
    return out

def d1(v1,v2):
    """                                                                                                     
    d1 uses a map                                                                        
    """
    return sum(map(mul,v1,v2))

def d3(v1,v2):
    """                                                                                                     
    d3 uses a starmap (itertools) to apply the mul operator on an zipped (v1,v2)                           
    """
    return sum(starmap(mul,zip(v1,v2)))

【问题讨论】:

    标签: python python-3.x algorithm


    【解决方案1】:
    import operator
    
    def sumproduct(*lists):
        return sum(reduce(operator.mul, data) for data in zip(*lists))
    

    对于python 3

    import operator
    import functools
    
    def sumproduct(*lists):
        return sum(functools.reduce(operator.mul, data) for data in zip(*lists))
    

    【讨论】:

    • 如果我需要 sumproduct 接受一个列表作为参数,我需要用 def sumproduct(lists) 替换 def sumproduct(*lists) 并保持 zip(*lists) 调用不变。
    • 较短的 alt def sumproduct(*lists): return sum(map(operator.mul, *lists)) ... 但仅适用于两个列表,尚不确定是否可以通过这种方式变得更简单。
    【解决方案2】:

    映射列表以创建产品列表,然后对其求和。

    这可以在一行中完成:

    sum(map(lambda Xi, Yi: Xi * Yi, ListX, ListY))
    

    【讨论】:

      【解决方案3】:

      旧的列表推导怎么样? (正如@Turksarama 提到的,这只适用于两个列表)

      sum([x * y for x, y in zip(*lists)])
      

      在 Python 3.6 中测试:

      In [532]: import random
      
      In [534]: x = [random.randint(0,100) for _ in range(100)]
      
      In [535]: y = [random.randint(0,100) for _ in range(100)]
      
      In [536]: lists = x, y
      

      使用列表推导

      In [543]: %timeit(sum([x * y for x, y in zip(*lists)]))
      8.73 µs ± 24.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      请注意,“元组”推导式是 slower

      In [537]: %timeit(sum(x * y for x, y in zip(*lists)))
      10.5 µs ± 170 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      使用map

      In [539]: %timeit(sum(map(lambda xi, yi: xi * yi, x, y)))
      12.3 µs ± 144 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
      

      使用functools.reduce

      In [542]: %timeit(sum(functools.reduce(operator.mul, data) for data in zip(*lists)))
      38.6 µs ± 330 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
      

      【讨论】:

      • 仅适用于两个列表,我认为这可能是仅有的一次因为这个原因,reduce 比列表理解更好。
      猜你喜欢
      • 1970-01-01
      • 2021-10-27
      • 2021-06-17
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多