2015-12-23 18 views
7

Jaki jest sposób pythonowy sumowania iloczyn wszystkich kombinacjach w danej listy, takie jak:Suma iloczynu kombinacji na liście

[1, 2, 3, 4] 
--> (1 * 2) + (1 * 3) + (1 * 4) + (2 * 3) + (2 * 4) + (3 * 4) = 35 

(W tym przykładzie Brałem wszystkich dwuelementowych kombinacje, ale mogło być inaczej.)

+2

wykonać kombinacje musiał składa się z 2 elementów? – 0x539

Odpowiedz

10

Zastosowanie itertools.combinations

>>> l = [1, 2, 3, 4] 
>>> sum([i*j for i,j in list(itertools.combinations(l, 2))]) 
35 
+1

Nie mogę zdecydować, którą odpowiedź wybrać jako "odpowiedź". Czy podejście Kevina jest w jakikolwiek sposób lepsze? (Być może w bardziej ogólnym ustawieniu, czy cokolwiek innego.) – blackened

+0

Czy nie powinien to być 'suma ([i * j dla i, j na liście (kombinacje (l, 2))))? –

+0

@blackened: Gdybym był tobą, przyjąłbym odpowiedź Avinasha, ponieważ jego odpowiedź jest jasna i prosta niż moja. Myślę, że moja odpowiedź była po prostu używana więcej funkcji zamiast operatora '*', nie jest szybszy niż Avinash, ale bardziej złożone. –

7
>>> a = [1, 2, 3, 4]  
>>> import operator 
>>> import itertools 
>>> sum(itertools.starmap(operator.mul, itertools.combinations(l, 2))) 
35 

itertools.combinations(a, 2) powraca:

>>> list(itertools.combinations(a, 2)) 
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] 
>>> 

I itertools.starmap() robi:

Złóż iterator, który oblicza funkcję używając argumentów uzyskane z iterable. Używane zamiast map(), gdy parametry argumentu są już zgrupowane w krotkach z pojedynczej iteracji (dane zostały "wstępnie zipowane").

Na koniec użyj sum() z generator comprehension, aby uzyskać ostateczne wyniki.

+1

Możesz również użyć 'itertools.starmap' zamiast" reduce': 'sum (itertools.starmap (operator.mul, itertools.combinations (l, 2)))... – chepner

+0

@chepner: Dobry punkt , nie wiem tego wcześniej. –

2

Nie jestem pewien co do podpowiedzi, ale można rozwiązać ten problem w prostszy sposób.

E.g. Na liście [a, b, c] => wynik może być zapisana jako

((a + b + c)^2 - (a^2 + b^2 + c^2))/2 

Tak więc, może być zapisany jako różnica kwadratu sumy listy i sumy kwadratów liście, podzielony przez 2.

można osiągnąć to samo co następuje w Pythonie:

a = [1,2,3,4] 
((sum(a) ** 2) - sum([x ** 2 for x in a]))/2 

PS Wiem, że problem można rozwiązać za pomocą itertools, a pytanie prosi w konkretny sposób o jego rozwiązanie. Myślę, że byłoby to łatwe, bez wypróbowania wszystkich kombinacji.

1

to również sumę górnego trójkąta zewnętrzny iloczyn wektora w tablicy ze sobą:

import numpy as np 
np.triu(np.outer([1,2,3,4],[1,2,3,4]),1).sum() 
35 

krok po kroku, to działa w następujący sposób:

# outer product 
np.outer([1,2,3,4],[1,2,3,4]) 

array([[ 1, 2, 3, 4], 
     [ 2, 4, 6, 8], 
     [ 3, 6, 9, 12], 
     [ 4, 8, 12, 16]]) 

# upper triangle 
np.triu(np.outer([1,2,3,4],[1,2,3,4]),1) 

array([[ 0, 2, 3, 4], 
     [ 0, 0, 6, 8], 
     [ 0, 0, 0, 12], 
     [ 0, 0, 0, 0]]) 

# then the sum, which is the non-zero elements 
np.triu(np.outer([1,2,3,4],[1,2,3,4]),1).sum() 
35