Para resumir los valores de los mismos elementos en una lista de tuplas mientras son cadenas

Si tengo lista de tuplas como esta:

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

¿Cómo puedo pasar la lista a esto?

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

es decir, para agregar el gasto del mismo artículo mientras que ambos elementos son una cadena en las tuplas. Tengo problemas con el precio de los artículos que son de cadena. Cualquier sugerencia sería muy apreciada. ¡Muchas gracias!

Estoy obteniendo la primera lista de esta manera:

 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)) 

Ahora my_list debería verse como se my_list arriba.

Puedes usar defaultdict para hacer esto:

 >>> 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')] 

Esto es bastante fácil usando un diccionario:

 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 

Edición: se olvidaron dos líneas

Si sus datos ya están agrupados como muestra de entrada, puede usar itertools.groupby , agrupando por cada primer elemento de las tuplas y sumndo los precios en cada grupo:

 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))] 

Salida:

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

Si no se ordenó, se puede llamar agrupado por groupby(sorted(my_list), itemgetter(0)) pero cambia la complejidad a n log n por lo que una opción de dictado puede ser mejor en ese caso.

También puede hacer el grupo en base a los data y olvidarse de crear una lista intermedia, csv.reader también dividirá los datos por usted:

 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))] 

Es posible que también sea mejor que deje los valores como ints y formatee cuando desee imprimir. También para manejar flotadores fundidos para flotar no int:

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

Cuando desee imprimir, puede agregar el signo de dólar y también el pad para que obtenga una salida con un formato agradable:

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

Simplemente puede utilizar un diccionario para resolver este problema.

 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 

Y si necesita una lista de tuplas, simplemente haga

 print sums.items() 

Y para obtener la salida que esperas,

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

Actualizar

Si tiene costos con valor de punto flotante, simplemente puede cambiar int para float así y el rest del código seguirá siendo el mismo,

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

Sólo por diversión, una sola línea:

 [(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))] 

En realidad no hagas esto.