Python usando la comprensión de enumerar dentro de la lista

125

Supongamos que tengo una lista como esta:

mylist = ["a","b","c","d"]

Para obtener los valores impresos junto con su índice, puedo usar la enumeratefunción de Python como esta

>>> for i,j in enumerate(mylist):
...     print i,j
...
0 a
1 b
2 c
3 d
>>>

Ahora, cuando trato de usarlo dentro de un list comprehensionme da este error

>>> [i,j for i,j in enumerate(mylist)]
  File "<stdin>", line 1
    [i,j for i,j in enumerate(mylist)]
           ^
SyntaxError: invalid syntax

Entonces, mi pregunta es: ¿cuál es la forma correcta de usar la comprensión de enumerar dentro de la lista?

RanRag
fuente

Respuestas:

166

Prueba esto:

[(i, j) for i, j in enumerate(mylist)]

Debes poner i,jdentro de una tupla para que la comprensión de la lista funcione. Alternativamente, dado que enumerate() ya devuelve una tupla, puede devolverla directamente sin desempaquetarla primero:

[pair for pair in enumerate(mylist)]

De cualquier manera, el resultado que se devuelve es el esperado:

> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
Óscar López
fuente
44
No es obligatorio ser una tupla. Cualquier expresión que use i y j que devuelva un valor funcionará
Alvaro
uso de enumeración es grande, ¿qué hay de lo que hace más eficiente el uso de itertools
Pramit
3
Sólo recuerde que una tupla es construido por el , no al (). "Poner i,jdentro de una tupla" no tiene sentido, ¡ya que i,jes una tupla! El problema es que el analizador de listas de compilación necesita los parens para el grupo de instrucciones.
cowbert
46

Para ser realmente claro, esto no tiene nada que ver enumeratey todo que ver con la sintaxis de comprensión de listas.

Esta comprensión de la lista devuelve una lista de tuplas:

[(i,j) for i in range(3) for j in 'abc']

esta es una lista de dictados:

[{i:j} for i in range(3) for j in 'abc']

una lista de listas:

[[i,j] for i in range(3) for j in 'abc']

Un error de sintaxis:

[i,j for i in range(3) for j in 'abc']

Lo cual es inconsistente (en mi humilde opinión) y confuso con la sintaxis de comprensión del diccionario:

>>> {i:j for i,j in enumerate('abcdef')}
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

Y un conjunto de tuplas:

>>> {(i,j) for i,j in enumerate('abcdef')}
set([(0, 'a'), (4, 'e'), (1, 'b'), (2, 'c'), (5, 'f'), (3, 'd')])

Como dijo Óscar López, puede pasar la tupla de enumeración directamente:

>>> [t for t in enumerate('abcdef') ] 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]
el lobo
fuente
32

O, si no insiste en usar una lista de comprensión:

>>> mylist = ["a","b","c","d"]
>>> list(enumerate(mylist))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
Pillmuncher
fuente
12

Si está utilizando listas largas, parece que la comprensión de la lista es más rápida, sin mencionar que es más legible.

~$ python -mtimeit -s"mylist = ['a','b','c','d']" "list(enumerate(mylist))"
1000000 loops, best of 3: 1.61 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[(i, j) for i, j in enumerate(mylist)]"
1000000 loops, best of 3: 0.978 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[t for t in enumerate(mylist)]"
1000000 loops, best of 3: 0.767 usec per loop
beardc
fuente
2
+1 No lo probé, pero apuesto a que [t for t in enumerate(my list)]es aún más rápido.
el lobo
11

Aquí hay una manera de hacerlo:

>>> mylist = ['a', 'b', 'c', 'd']
>>> [item for item in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Alternativamente, puedes hacer:

>>> [(i, j) for i, j in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

La razón por la que obtuvo un error fue porque le faltaba el () iy jpara convertirlo en una tupla.

Simeon Visser
fuente
6

Sé explícito sobre las tuplas.

[(i, j) for (i, j) in enumerate(mylist)]
Ignacio Vazquez-Abrams
fuente
0

Toda gran respuesta chicos. Sé que la pregunta aquí es específica para la enumeración, pero ¿qué tal algo como esto, solo otra perspectiva?

from itertools import izip, count
a = ["5", "6", "1", "2"]
tupleList = list( izip( count(), a ) )
print(tupleList)

Se vuelve más poderoso, si uno tiene que iterar múltiples listas en paralelo en términos de rendimiento. Solo un pensamiento

a = ["5", "6", "1", "2"]
b = ["a", "b", "c", "d"]
tupleList = list( izip( count(), a, b ) )
print(tupleList)
Pramit
fuente