2010-10-03 4 views
8

Попытка имитировать функцию SUMPRODUCT в Excel:сумма произведений для нескольких списков в Python

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

где п число элементов в каждом векторе.

Это похоже на точечный продукт, но для нескольких векторов. Я читал the very detailed discussion обычного продукта точки, но я не знаю, как его можно довести до нескольких векторов. Для справки, я копирую оптимизированный код, предложенный там, который я портировал (тривиально) на Python 3. BTW, для точечного продукта последний подход все еще выигрывает в 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))) 

ответ

16
import operator 

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

для питона 3

import operator 
import functools 

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

И если мне нужно SUMPRODUCT принять список в качестве аргумента, мне нужно заменить 'Защиту SUMPRODUCT (* списки)' с 'Def SUMPRODUCT (списки)' и сохранить 'zip (* lists)' вызов без изменений. – max

+1

Более короткий alt 'def sumproduct (* lists): return sum (map (operator.mul, * lists))' ... но только для двух списков, но не уверен, может ли это сделать проще. – hhh

5

карты списка, чтобы создать список продуктов, а затем подвести его. в один лайнер:

сумма (карта (лямбда Xi, Yi: Xi * Yi, ListX, Listy))

3

насчет старых хороших списковых?

sum([x*y for x,y in zip(*lists)]) 
Смежные вопросы