Python utilisant enumerate dans la compréhension de liste

125

Supposons que j'ai une liste comme celle-ci:

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

Pour obtenir les valeurs imprimées avec leur index, je peux utiliser la enumeratefonction de Python comme ceci

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

Maintenant, quand j'essaye de l'utiliser à l'intérieur d'un list comprehensionça me donne cette erreur

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

Donc, ma question est: quelle est la bonne façon d'utiliser enumerate dans la compréhension de liste?

RanRag
la source

Réponses:

166

Essaye ça:

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

Vous devez mettre i,jdans un tuple pour que la compréhension de la liste fonctionne. Alternativement, étant donné que renvoie enumerate() déjà un tuple, vous pouvez le retourner directement sans le déballer au préalable:

[pair for pair in enumerate(mylist)]

Dans tous les cas, le résultat renvoyé est celui attendu:

> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
Óscar López
la source
4
Pas obligatoire pour être un tuple. Toute expression utilisant i et j qui renvoie une valeur fera l'affaire
Alvaro
l'utilisation du dénombrement est excellente, que diriez-vous de la rendre plus efficace en utilisant itertools
Pramit
3
Rappelez - vous qu'un tuple est construit par le , non le (). Donc "mettre i,jdans un tuple" n'a aucun sens, puisque i,jc'est déjà un tuple! Le problème est que l'analyseur de compilation de liste a besoin des parenthèses pour le groupe d'instructions.
cowbert
46

Juste pour être très clair, cela n'a rien à voir avec enumerateet tout à voir avec la syntaxe de compréhension de liste.

Cette compréhension de liste renvoie une liste de tuples:

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

voici une liste de dictats:

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

une liste de listes:

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

une erreur de syntaxe:

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

Ce qui est incohérent (IMHO) et déroutant avec la syntaxe de compréhension du dictionnaire:

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

Et un ensemble de tuples:

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

Comme Óscar López l'a déclaré, vous pouvez simplement passer le tuple d'énumération directement:

>>> [t for t in enumerate('abcdef') ] 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]
le loup
la source
32

Ou, si vous n'insistez pas pour utiliser une compréhension de liste:

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

Si vous utilisez de longues listes, il semble que la compréhension de la liste soit plus rapide, pour ne pas dire plus lisible.

~$ 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
barbe
la source
2
+1 Je ne l'ai pas testé, mais je parie que [t for t in enumerate(my list)]c'est encore plus rapide.
le loup
11

Voici une façon de le faire:

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

Alternativement, vous pouvez faire:

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

La raison pour laquelle vous avez obtenu une erreur était que vous manquiez le () autour iet jd'en faire un tuple.

Siméon Visser
la source
6

Soyez explicite sur les tuples.

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

Tous les gars de bonne réponse. Je sais que la question ici est spécifique à l'énumération, mais qu'en est-il de quelque chose comme ça, juste une autre perspective

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

Cela devient plus puissant, si l'on doit itérer plusieurs listes en parallèle en termes de performances. Juste une pensée

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