Python list_of_tuples: sum el segundo valor de cada tupla, solo si el primer valor de la tupla es == algo

Tengo una lista de tuplas “etiquetadas” … donde está cada tupla (tag_id, valor) … así:

my_list = [(tag_A, 100), (tag_A, 200), (tag_A, 300), (tag_A, 400), (tag_B, 400), (tag_B, 600)] 

Quiero sumr los valores de cada tupla con la misma etiqueta … para que:

 sum_of_all_values_with_tag_A() = 1000 sum_of_all_values_with_tag_B() = 1000 

No puedo imaginar una forma sencilla de hacer los pitones.

 sum(set(value for tag_id, value in my_list)) 

… devuelve la sum de TODOS los valores.

Supongo que puedo envolver eso con un bucle for o while, de modo que solo las tuplas con la etiqueta que quiero sumr sean tocadas por esa expresión …? Necesito sumr los valores asociados con ambas tags … dando como resultado dos totales diferentes, diferenciados como se muestra arriba. Pero no puedo asimilar una syntax elegante para tal cosa.

Esto está sucediendo dentro de una función preexistente. Sería genial hacerlo sin funciones de anidación.

Cualquier sugerencia es apreciada!

Enfoque

Ponga sus datos en un valor defaultdict(list) . Resumir eso.

Código

 from collections import defaultdict my_list = [('tag_A', 100), ('tag_A', 200), ('tag_A', 300), ('tag_A', 400), ('tag_B', 400), ('tag_B', 600)] d = defaultdict(list) for tag, num in my_list: d[tag].append(num) 

Prueba

 >>> from collections import defaultdict >>> my_list = [('tag_A', 100), ('tag_A', 200), ('tag_A', 300), ('tag_A', 400), ('tag_B', 400), ('tag_B', 600)] >>> >>> d = defaultdict(list) >>> for tag, num in my_list: ... d[tag].append(num) ... >>> from pprint import pprint >>> pprint(dict(d)) {'tag_A': [100, 200, 300, 400], 'tag_B': [400, 600]} >>> >>> pprint({k: sum(v) for k, v in d.iteritems()}) {'tag_A': 1000, 'tag_B': 1000} 

Rutina de resumen alternativa

 def summarize_by_tag(d): for k, v in d.iteritems(): print k, sum(v) >>> summarize_by_tag(d) tag_A 1000 tag_B 1000 

Use una expresión generadora para sumr por etiqueta:

 sum(val for tag, val in my_list if tag == tag_A) 

Puede ordenar las tags y luego usar itertools.groupby para crear grupos y sums por etiqueta:

 from itertools import groupby from operator import itemgetter key = itemgetter(0) # tag sums = {tag: sum(tup[1] for tup in group) for tag, group in groupby(sorted(my_list, key=key), key=key)} 

Esto produciría un diccionario que asigna tags a la sum por etiqueta:

 >>> from itertools import groupby >>> from operator import itemgetter >>> tag_A, tag_B = 'A', 'B' >>> my_list = [(tag_A, 100), (tag_A, 200), (tag_A, 300), (tag_A, 400), (tag_B, 400), (tag_B, 600)] >>> key = itemgetter(0) # tag >>> sums = {tag: sum(tup[1] for tup in group) ... for tag, group in groupby(sorted(my_list, key=key), key=key)} >>> print sums {'A': 1000, 'B': 1000} 

Como en otras respuestas, solo usaría el defaultdict pero a menos que necesite los grupos nuevamente más tarde. Solo sumlos como tu grupo. my_list podría ser una iterable muy grande y no estarás almacenando todo en la memoria.

 from collections import defaultdict my_list = [('tag_A', 100), ('tag_A', 200), ('tag_A', 300), ('tag_A', 400), ('tag_B', 400), ('tag_B', 600)] result = defaultdict(int) for tag, value in my_list: result[tag] += value print result defaultdict(, {'tag_A': 1000, 'tag_B': 1000}) 

Sin importar nada. .

 mysum={} my_list = [('tag_A', 100), ('tag_A', 200), ('tag_A', 300), ('tag_A', 400), ('tag_B', 400), ('tag_B', 600)] for x in my_list: mysum.setdefault(x[0],0) mysum[x[0]]+=x[1] print mysum 

salida::

 {'tag_A': 1000, 'tag_B': 1000}