Suma los números por letras en la lista de tuplas

Tengo una lista de tuplas:

[ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ] 

Estoy tratando de resumir todos los números que tienen la misma letra. Es decir quiero salir

 [('A', 150), ('B', 70), ('C',10)] 

He intentado usar el conjunto para obtener los valores únicos, pero luego, cuando bash comparar los primeros elementos con el conjunto, obtengo

 TypeError: unsupported operand type(s) for +: 'int' and 'str' 

¿Alguna solución rápida para hacer coincidir los números por letra?

Aquí hay un (¿y medio?) – trazador de líneas: grupo por letra (para lo que necesita ordenar antes), luego tome la sum de las segundas entradas de sus tuplas.

 from itertools import groupby from operator import itemgetter data = [('A', 100), ('B', 50), ('A', 50), ('B', 20), ('C', 10)] res = [(k, sum(map(itemgetter(1), g))) for k, g in groupby(sorted(data, key=itemgetter(0)), key=itemgetter(0))] print(res) // => [('A', 150), ('B', 70), ('C', 10)] 

Lo anterior es O (n log n): la clasificación es la operación más costosa. Si su lista de entrada es realmente grande, es posible que el siguiente enfoque O (n) le sirva mejor:

 from collections import defaultdict data = [('A', 100), ('B', 50), ('A', 50), ('B', 20), ('C', 10)] d = defaultdict(int) for letter, value in data: d[letter] += value res = list(d.items()) print(res) // => [('B', 70), ('C', 10), ('A', 150)] 

¿Qué tal esto? (Asumiendo que a es el nombre de la tupla que ha proporcionado)

 letters_to_numbers = {} for i in a: if i[0] in letters_to_numbers: letters_to_numbers[i[0]] += i[1] else: letters_to_numbers[i[0]] = i[1] b = letters_to_numbers.items() 

Los elementos de la tupla b resultante no estarán en ningún orden en particular.

Para lograr esto, primero cree un diccionario para almacenar sus valores. Luego, convierta el objeto dict en una tuple list usando .items() A continuación se muestra el código de ejemplo sobre cómo lograr esto:

 my_list = [ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ] my_dict = {} for key, val in my_list: if key in my_dict: my_dict[key] += val else: my_dict[key] = val my_dict.items() # Output: [('A', 150), ('C', 10), ('B', 70)] 

¿Qué está generando la lista de tuplas? ¿Eres tú? Si es así, ¿por qué no intenta un punto predeterminado (lista) para agregar los valores a la letra correcta al momento de hacer la lista de tuplas? Entonces simplemente puedes sumrlos. Vea el ejemplo a continuación.

 >>> from collections import defaultdict >>> val_store = defaultdict(list) >>> # next lines are me simulating the creation of the tuple >>> val_store['A'].append(10) >>> val_store['B'].append(20) >>> val_store['C'].append(30) >>> val_store defaultdict(, {'C': [30], 'A': [10], 'B': [20]}) >>> val_store['A'].append(10) >>> val_store['C'].append(30) >>> val_store['B'].append(20) >>> val_store defaultdict(, {'C': [30, 30], 'A': [10, 10], 'B': [20, 20]}) >>> for val in val_store: ... print(val, sum(val_store[val])) ... C 60 A 20 B 40 
 >>> from collections import Counter >>> c = Counter() >>> for k, num in items: c[k] += num >>> c.items() [('A', 150), ('C', 10), ('B', 70)] 

Una versión de forro menos eficiente (pero más agradable):

 >>> Counter(k for k, num in items for i in range(num)).items() [('A', 150), ('C', 10), ('B', 70)] 

Prueba esto:

 a = [('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ] letters = set([s[0] for s in a]) new_a = [] for l in letters: nums = [s[1] for s in a if s[0] == l] new_a.append((l, sum(nums))) print new_a 

Resultados:

 [('A', 150), ('C', 10), ('B', 70)] 

Un enfoque más sencillo.

 x = [('A',100),('B',50),('A',50),('B',20),('C',10)] y = {} for _tuple in x: if _tuple[0] in y: y[_tuple[0]] += _tuple[1] else: y[_tuple[0]] = _tuple[1] print [(k,v) for k,v in y.iteritems()] 

Un trazador de líneas:

 >>> x = [ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ] >>> { ... k: reduce(lambda u, v: u + v, [y[1] for y in x if y[0] == k]) ... for k in [y[0] for y in x] ... }.items() [('A', 150), ('C', 10), ('B', 70)]