2009-03-12 15 views
20

Tengo una lista de tuplas (siempre pares) como este:¿Cómo puedo sumar el primer valor en cada tupla en una lista de tuplas en Python?

[(0, 1), (2, 3), (5, 7), (2, 1)] 

me gustaría encontrar la suma de los primeros elementos de cada par, es decir:

0 + 2 + 5 + 2 

¿Cómo puedo hacer esto en Python? En este momento estoy iterando a través de la lista:

sum = 0 
for pair in list_of_pairs: 
    sum += pair[0] 

Tengo la sensación de que debe haber una manera más Ptónica.

+0

¿Está limitado a versiones de Python inferiores a 2.4? Lo pregunto porque la respuesta seleccionada crea innecesariamente una lista temporal. El trivial one-liner en python> = 24 es 'suma (p [0] para p en list_of_pairs)'. – juanchopanza

Respuesta

48

Una versión compatible con Python 2.3 es

sum([pair[0] for pair in list_of_pairs]) 

o en versiones recientes de Python, ver this answer o this one.

+2

Quité los corchetes, porque lo hacen más lento ya que Python crea la lista primero. sum() funciona bien con iteradores. –

+1

gs, rompió el código de la misma forma en que David mencionó que el código de SilentGhost no funcionó. Has convertido la comprensión de la lista en una expresión de generador (no un iterador), que no existía hasta Python 2.4. –

+0

Retiré la edición porque si vas a usar un método que no es compatible con Python 2.3, bien podría ser el de la respuesta de SilentGhost. –

33
sum(i for i, j in list_of_pairs) 

hará también.

+0

Lo pensé al principio, pero cuando lo intenté en el Python más rápido que pude acceder, generó un error de sintaxis :-(Resulta que estaba probando en Python 2.3, aunque ... +1 de todos modos –

+0

+1: prefiero esto - - Las tuplas tienen un tamaño fijo y generalmente sabes cuál es el tamaño. –

+1

También me gusta este enfoque. Pero la solución de David también funciona con n-tuplas, lo que podría ser preferible, dependiendo del problema real. –

4

Si tiene una lista muy grande o un generador que produce una gran cantidad de pares, es posible que desee utilizar un enfoque basado en generador. Por diversión también uso itemgetter() y imap(). Sin embargo, un enfoque basado en un generador simple podría ser suficiente.

import operator 
import itertools 
idx0 = operator.itemgetter(0) 
list_of_pairs = [(0, 1), (2, 3), (5, 7), (2, 1)] 
sum(itertools.imap(idx0, list_of_pairs) 

Editar: itertools.imap() está disponible en Python 2.3. Entonces puedes usar un enfoque basado en generador allí también.

+0

No es realmente más rápido que las otras dos soluciones. –

+0

No puedo leer nada sobre la velocidad en la pregunta. –

+0

La velocidad siempre es buena, y al menos debería mencionarse en las respuestas. –

3

oscuro (pero divertido) respuesta:

>>> sum(zip(*list_of_pairs)[0]) 
9 

O cuando de Zip son iterables sólo esto debería funcionar:

>>> sum(zip(*list_of_pairs).__next__()) 
9 
+0

no funciona para py3k: los objetos zip son unsubscriptable – SilentGhost

+0

.next() debería funcionar bien en ese caso –

+0

mmm, el objeto 'zip' no tiene atributo 'next'. – SilentGhost

12

que recomiendo:

sum(i for i, _ in list_of_pairs) 

Nota:

Usando la variable _ (o __ para evitar la conflictividad con el alias de gettext) en lugar de j tiene al menos dos ventajas:

  1. _ (acrónimo de marcador de posición) tiene una mejor legibilidad
  2. pylint no lo hará quejarse: "Variable no utilizada 'j'"
0

A continuación se muestra el código de muestra, también puede especificar el rango de la lista.

def test_lst_sum(): 
    lst = [1, 3, 5] 
    print sum(lst) # 9 
    print sum(lst[1:]) # 8 

    print sum(lst[5:]) # 0 out of range so return 0 
    print sum(lst[5:-1]) # 0 

    print sum(lst[1: -1]) # 3 

    lst_tp = [('33', 1), ('88', 2), ('22', 3), ('44', 4)] 
    print sum(x[1] for x in lst_tp[1:]) # 9 
Cuestiones relacionadas