2012-07-25 4 views
7

Lassen Sie uns sagen, ich habe die folgenden zwei Listen von TupelnPython einfachste Weg, um Sum Liste Überschneidung der Liste von Tupeln

myList = [(1, 7), (3, 3), (5, 9)] 
otherList = [(2, 4), (3, 5), (5, 2), (7, 8)] 

returns => [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] 

Ich möchte einen Druckvorgang entwerfen, die auf durch die Überprüfung für alle Kreuzungen dieser beiden Listen verschmilzt das erste Element des Tupels, wenn es Kreuzungen gibt, füge die zweiten Elemente jedes fraglichen Tupels hinzu (füge die beiden zusammen). Nach der Operation würde ich gerne nach dem ersten Element sortieren.

Ich veröffentliche auch das, weil ich es ist ein ziemlich häufiges Problem denken, dass eine offensichtliche Lösung hat, aber ich glaube, dass es auf diese Frage sehr pythonic Lösungen sein könnte;)

Antwort

14

Verwenden Sie ein Wörterbuch für das Ergebnis:

Wenn Sie eine Liste von Tupeln möchten, können Sie es über result.items() erhalten. Die resultierende Liste wird in beliebiger Reihenfolge sein, aber natürlich können Sie sie auch sortieren, falls gewünscht.

(. Beachten Sie, dass ich Ihre Listen mit Python Stil Konventionen entsprechen umbenannt)

+0

Wirklich sauber. Schöne Lösung! –

+0

Beachten Sie, dass 'result.items()' ein 'dict_items' Objekt in Python 3 zurückgibt. Natürlich können Sie' list (result.items()) 'immer tun. – kamek

1

Verfahren unter Verwendung von itertools:

>>> myList = [(1, 7), (3, 3), (5, 9)] 
>>> otherList = [(2, 4), (3, 5), (5, 2), (7, 8)] 

>>> import itertools 
>>> merged = [] 
>>> for k, g in itertools.groupby(sorted(myList + otherList), lambda e: e[0]): 
... merged.append((k, sum(e[1] for e in g))) 
... 
>>> merged 
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] 

Dieser erste verkettet die beiden Listen zusammen und sortiert sie. itertools.groupby gibt die Elemente der zusammengeführten Liste zurück, die nach dem ersten Element des Tupels gruppiert sind. Es fasst sie also zusammen und fügt sie in die zusammengeführte Liste ein.

4

Verwenden defaultdict:

from collections import defaultdict 
results_dict = defaultdict(int) 
results_dict.update(my_list) 
for a, b in other_list: 
    results_dict[a] += b 
results = sorted(results_dict.items()) 

Hinweis: Wenn Sequenzen Sortierung, sorted Sorten durch das erste Element in der Sequenz. Wenn die ersten Elemente gleich sind, vergleicht es das zweite Element. Sie können sorted eine Funktion geben, indem zu sortieren, mit dem key Schlüsselwort-Argument:

results = sorted(results_dict.items(), key=lambda x: x[1]) #sort by the 2nd item 

oder

results = sorted(results_dict.items(), key=lambda x: abs(x[0])) #sort by absolute value 
+0

(+1) Ich weiß nicht, wie ich die ganze Zeit nicht bemerkt habe, dass 'dict.update' eine Sequenz akzeptiert, die der des dict-Konstruktors entspricht. Außerdem ist es trivial, nach dem ersten OP des Tupels zu sortieren ('results = sorted (results_dict.items())') – mgilson

+0

@mgilson: Danke! Ich habe den Teil über ein sortiertes Ergebnis verpasst. Wird bearbeiten. –

+0

@mgilson: Anscheinend wurde 'accept()' akzeptiert iterables in 2.4 eingeführt. –

0
>>> [(k, sum(v for x,v in myList + otherList if k == x)) for k in dict(myList + otherList).keys()] 
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] 
>>> 

sowohl für python2.7 getestet und 3.2
dict(myList + otherList).keys() gibt eine iterable ein enthält Satz der Schlüssel für die verbundenen Listen
sum(...) nimmt 'k', um wieder durch die verbundene Liste Schleife und summieren Tupel-Elemente 'v' wo k == x

... aber die zusätzliche Schleife fügt Verarbeitungsaufwand hinzu. Die Verwendung eines expliziten Wörterbuchs wie von Sven Marnach vorgeschlagen, vermeidet es.

Verwandte Themen