2015-12-23 26 views
7

Was ist der Pythonic Art und Weise das Produkt aller Kombinationen in einer vorgegebenen Liste von Summieren, wie zum Beispiel:Summe Produkt von Kombinationen in einer Liste

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

(in diesem Beispiel das ich gemacht habe all das aus zwei Elementen Kombinationen, aber es könnte anders sein.)

+2

tun die Kombinationen müssen bestehen aus 2 Elementen? – 0x539

Antwort

10

Verwenden itertools.combinations

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

Ich kann nicht entscheiden, welche Antwort als "die Antwort" wählen. Ist Kevins Vorgehensweise in irgendeiner Weise überlegen? (Vielleicht in einer allgemeineren Einstellung oder was auch immer.) – blackened

+0

Sollte es nicht 'sum sein ([i * j für i, j in der Liste (Kombinationen (l, 2))])? –

+0

@blacked: Wenn ich du wäre, würde ich Avinashs Antwort akzeptieren, da seine Antwort klar und einfach ist. Ich denke meine Antwort wurde nur mehr Funktion anstelle von '*' Operator verwendet, es ist nicht schneller als Avinash, aber komplexer. –

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

itertools.combinations(a, 2) kehrt:

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

Und itertools.starmap() tut:

einen Iterator machen, dass die Funktion aus der iterable erhalten mit Argumenten berechnet. Wird anstelle von map() verwendet, wenn die Argumentparameter bereits in Tupeln aus einem einzelnen iterierbaren Objekt gruppiert sind (die Daten wurden "vor gezippt").

Schließlich verwenden sum() mit einem generator comprehension die endgültigen Ergebnisse zu erhalten.

+1

Sie können auch 'itertools.starmap' anstelle von' reduce' verwenden: 'sum (itertools.starmap (operator.mul, itertools.combinations (l, 2)))'. – chepner

+0

@chepner: Guter Punkt Ich weiß das vorher nicht. –

2

Ich bin mir nicht sicher über die Pythonic Art, aber Sie könnten dieses Problem in eine einfachere lösen.

z. Eine Liste [a, b, c] => Ergebnis auch als

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

So geschrieben werden kann, kann es als Differenz von Quadrat der Summe der Liste und Summe der Quadrate der Liste geschrieben, durch 2 geteilt.

Sie können das gleiche erreichen wie in python folgt:

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

PS Ich weiß, dass das Problem mit Hilfe von itertools gelöst werden kann und fragt speziell nach dem pythonischen Weg, um es zu lösen. Ich denke, es wäre sehr einfach, dies zu tun, ohne alle Kombinationen auszuprobieren.

1

Dies ist auch die Summe aus dem oberen Dreieck des äußeren Vektorprodukt des Arrays mit sich selbst:

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

Schritt für Schritt es wie folgt funktioniert:

# 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 
Verwandte Themen