2016-03-19 8 views
2

Wenn ich Liste von Tupeln wie diese:Um auf Werte von gleichen Elementen in einer Liste von Tupeln zu summieren, während sie Zeichenfolge sind

my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')] 

wie kann ich die Liste dazu drehen:

[('books', '$15'), ('ink', '$20'), ('paper', '$50')] 

ie, um die Ausgaben desselben Elements hinzuzufügen, während beide Elemente eine Zeichenfolge in den Tupeln sind. Ich habe ein Problem mit den Preiselementen, die Zeichenfolge sind. Jeder Hinweis würde sehr geschätzt werden. Danke vielmals!

Ich erhalte die erste Liste auf diese Weise:

my_list=[] 
for line in data: 
     item, price = line.strip('\n').split(',') 
     cost = ["{:s}".format(item.strip()), "${:.2f}".format(float(price))] 
     my_list.append(tuple(cost)) 

Jetzt my_list wie oben angegeben aussehen sollte.

+2

Bitte beachten Sie auch die Formatierungsoptionen im Editor. Markieren Sie den Codeabschnitt und drücken Sie dann Strg-K. – roadrunner66

+0

Gibt es einen Grund, warum Sie die Kosten als String speichern, dem ein '$' vorangestellt ist, anstatt einfach nur 'float'? – Holt

+3

@Holt: Sie würden nicht wollen, für monetäre Werte zu schweben; Ungenauigkeit kann dich töten. 'decimal.Decimal' für alle finanziellen Berechnungen. – ShadowRanger

Antwort

0

Das ist ziemlich einfach, ein Wörterbuch mit:

result={} #initialize an empty dictionary 
for (type,cost) in my_list: 
    if type not in result.keys(): 
     result[type]=int(cost[1:]) #add entry 
    else: 
     result[type]=result[type]+int(cost[1:]) #increment cost 

#make dictionary a list again 
dictlist=[] 
for key, value in result.iteritems(): 
    temp = [key,"$"+str(value)] #add dollar sign 
    dictlist.append(temp) 

print dictlist 

Edit: vergessen haben zwei Linien

0

Sie können einfach ein Wörterbuch, um dieses Problem zu lösen.

my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), 
     ('paper', '$15'), ('paper', '$20'), ('paper', '$15')] 

sums = {} 
for item, price in my_list: 
    sums[item] = sums.get(item, 0) + int(price[1:]) 

print sums 

Und wenn Sie Liste von Tupeln benötigen, tun nur

print sums.items() 

Und Ihr die Ausgabe, die Sie erwarten zu bekommen,

print [(item, '$' + str(price)) for item, price in sums.items()] 

aktualisieren

Wenn Sie Kosten mit Gleitkommawert, können Sie einfachändernzu float wie diese und Rest des Codes bleibt gleich,

sums[item] = sums.get(item, 0) + float(price[1:]) 
+1

löschst du auch diesen und schreibst eine weitere Antwort, wenn du einen weiteren Downvote bekommst? – styvane

+0

Es war meine Schuld, die Frage zuerst nicht gelesen zu haben. Dann habe ich es bekommen und richtig geantwortet. Ich dachte, eine neue Antwort Welt wäre hilfreich und wenn das eine schlechte Sache ist, warum gibt es eine Option, mehrere Antworten zu posten. Übrigens, wenn Sie nur deswegen ablehnen würden, würde ich Ihren Gehorsam gegenüber den Richtlinien dieser Seiten in Frage stellen. und nein, ich werde diese Antwort nicht löschen. – Muctadir

+0

Wie wäre es, wenn ich: my_list = [('Milch', '$ 2.35'), ('Brot', '$ 1.95'), ('Chips', '$ 2.54'), ('Milch', '$ 2.38')), ('Milch', '$ 2.31'), ('Brot', '$ 1.90')] – Korchagin

2

Sie defaultdict dies tun können:

>>> from collections import defaultdict 
>>> my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')] 
>>> res = defaultdict(list) 
>>> for item, price in my_list: 
...  res[item].append(int(price.strip('$'))) 
... 
>>> total = [(k, "${}".format(sum(v))) for k, v in res.items()] 
>>> total 
[('ink', '$20'), ('books', '$15'), ('paper', '$50')] 
-1

Just for fun, ein Einzeiler:

[(k,'$'+str(sum(int(e[1][1:]) for e in my_list if e[0]==k))) for k in set(map(lambda x:x[0], my_list))] 

Tun Sie das eigentlich nicht.

0

Wenn Ihre Daten bereits wie Sie Abtastwerteingang gruppiert ist, können Sie itertools.groupby verwenden, die von jedem ersten Element der Tupel Gruppierung und Summieren der Preise in jeder Gruppe:

from itertools import groupby 
from operator import itemgetter 

my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')] 

grouped = [(k, "${}".format(sum(int(s[1][1:]) for s in v)))  
       for k ,v in groupby(my_list, itemgetter(0))] 

Ausgang:

[('books', '$15'), ('ink', '$20'), ('paper', '$50')] 

Wenn es nicht bestellt wurde, könnten Sie sortierte groupby(sorted(my_list), itemgetter(0)) aufrufen, ändert aber die Komplexität zu n log n, so dass eine dict-Option in diesem Fall besser sein kann.

Sie können auch die groupby auf data tun und vergessen eine Zwischenliste erstellen, wird csv.reader aufgeteilt auch die Daten für Sie:

from itertools import groupby 
from operator import itemgetter 

from csv import reader 
grouped = [(k, "${}".format(sum(int(s[1]) for s in v))) 
       for k, v in groupby(reader(data), itemgetter(0))] 

Sie besser sein könnte auch die Werte als ints und Formatierung zu verlassen, wenn Sie wollen ausgeben. Auch zu handhaben Schwimmer zu gieße Schwimmer nicht int:

from csv import reader 
grouped = [(k, sum(float(s[1]) for s in v)) 
       for k, v in groupby(reader(data), itemgetter(0))] 

Wenn Sie ausgeben möchten, können Sie das Dollarzeichen hinzufügen und auch Kissen, so dass Sie schön formatierte Ausgabe:

In [10]: "${:.2f}".format(1.0) 
Out[10]: '$1.00' 
+0

Danke. Aber, wie wäre es im Fall, my_list = [('Milch', $ 2,35 '), (' Brot ',' $ 1,95 '), (' Chips ',' $ 2,54 '), (' Milch ',' $ 2,38 ')), ('Milch', '$ 2.31'), ('Brot', '$ 1.90')] – Korchagin

+0

Verwenden Sie einfach Float Instad von Int –

+0

Ich könnte es beheben. Vielen Dank für die Hilfe. – Korchagin

Verwandte Themen