¿Cómo sumo las tuplas en una lista donde el primer valor es el mismo?

Tengo una lista de acciones y posiciones como tuplas. Positivo para la compra, negativo para la venta. Ejemplo:

p = [('AAPL', 50), ('AAPL', -50), ('RY', 100), ('RY', -43)] 

¿Cómo puedo sumr las posiciones de las acciones, para obtener las tenencias actuales?

 result = [('AAPL', 0), ('RY', 57)] 

¿Qué tal esto? Puedes leer sobre collections.defaultdict .

 >>> from collections import defaultdict >>> testDict = defaultdict(int) >>> p = [('AAPL', 50), ('AAPL', -50), ('RY', 100), ('RY', -43)] >>> for key, val in p: testDict[key] += val >>> testDict.items() [('AAPL', 0), ('RY', 57)] 

Aquí hay una solución que no implica importar:

 >>> p = [('AAPL', 50), ('AAPL', -50), ('RY', 100), ('RY', -43)] >>> d = {x:0 for x,_ in p} >>> for name,num in p: d[name] += num ... >>> Result = map(tuple, d.items()) >>> Result [('AAPL', 0), ('RY', 57)] >>> 

Tenga en cuenta que esto es para Python 2.x. En 3.x, deberá hacer: Result = list(map(tuple, d.items())) .

Haría esto usando collections.Counter . collections.Counter :

 In [2]: from collections import Counter In [3]: c = Counter() In [4]: for k, v in p: ...: c[k] += v ...: In [5]: c Out[5]: Counter({'AAPL': 0, 'RY': 57}) 

Luego, puede llamar al método most_common de objetos Counter para obtener una lista de tuplas ordenadas por los valores en orden descendente.

 In [5]: c.most_common() Out[5]: [('RY', 57), ('AAPL', 0)] 

En caso de que necesite ordenar las tuplas por sus primeros elementos, use sorted(c.items()) :

 In [6]: sorted(c.items()) Out[6]: [('AAPL', 0), ('RY', 57)] 

sin ningún tipo de bucles explícitos:

 >>> from itertools import groupby >>> from operator import itemgetter >>> p = [('AAPL', 50), ('AAPL', -50), ('RY', 100), ('RY', -43)] >>> map(lambda g: (g[0], sum(map(itemgetter(1), g[1]))), ... groupby(sorted(p), itemgetter(0))) [('AAPL', 0), ('RY', 57)]