Accéder à l'index dans les boucles 'for'?

3608

Comment accéder à l'index dans un for boucle comme celle-ci?

ints = [8, 23, 45, 12, 78]
for i in ints:
    print('item #{} = {}'.format(???, i))

Je veux obtenir cette sortie:

item #1 = 8
item #2 = 23
item #3 = 45
item #4 = 12
item #5 = 78

Lorsque je le boucle à l'aide d'une forboucle, comment accéder à l'index de la boucle, de 1 à 5 dans ce cas?

Joan Venge
la source
42
Notez que les index en python commencent à 0, donc les index de votre liste d'exemples sont de 0 à 4 et non de 1 à 5
plugwash

Réponses:

6124

L'utilisation d'une variable d'état supplémentaire, telle qu'une variable d'index (que vous utiliseriez normalement dans des langages tels que C ou PHP), est considérée comme non pythonique.

La meilleure option est d'utiliser la fonction intégrée enumerate(), disponible en Python 2 et 3:

for idx, val in enumerate(ints):
    print(idx, val)

Consultez PEP 279 pour en savoir plus.

Mike Hordecki
la source
61
Comme Aaron le souligne ci-dessous, utilisez start = 1 si vous voulez obtenir 1-5 au lieu de 0-4.
clozach
2
N'encourt enumeratepas de frais généraux supplémentaires?
TheRealChx101
@ TheRealChx101 selon mes tests (Python 3.6.3) la différence est négligeable et parfois même en faveur de enumerate.
Błotosmętek
806

En utilisant une boucle for, comment accéder à l'index de boucle, de 1 à 5 dans ce cas?

Utilisez enumeratepour obtenir l'index avec l'élément lors de l'itération:

for index, item in enumerate(items):
    print(index, item)

Et notez que les index de Python commencent à zéro, vous obtiendrez donc 0 à 4 avec ce qui précède. Si vous voulez le nombre, 1 à 5, procédez comme suit:

for count, item in enumerate(items, start=1):
    print(count, item)

Flux de contrôle unidiomatique

Ce que vous demandez, c'est l'équivalent Pythonic des éléments suivants, qui est l'algorithme que la plupart des programmeurs de langages de niveau inférieur utiliseraient:

index = 0            # Python's indexing starts at zero
for item in items:   # Python's for loops are a "for each" loop 
    print(index, item)
    index += 1

Ou dans les langues qui n'ont pas de boucle pour chaque:

index = 0
while index < len(items):
    print(index, items[index])
    index += 1

ou parfois plus communément (mais de manière non unidirectionnelle) trouvé en Python:

for index in range(len(items)):
    print(index, items[index])

Utilisez la fonction Enumerate

La enumeratefonction de Python réduit l'encombrement visuel en masquant la comptabilité des index et en encapsulant l'itérable dans un autre itérable (un enumerateobjet) qui produit un tuple à deux éléments de l'index et l'élément que l'itérable d'origine fournirait. Cela ressemble à ceci:

for index, item in enumerate(items, start=0):   # default is zero
    print(index, item)

Cet exemple de code est assez bien le exemple canonique de la différence entre le code qui est idiomatique de Python et le code qui ne l'est pas. Le code idiomatique est un Python sophistiqué (mais pas compliqué), écrit de la manière dont il était destiné à être utilisé. Le code idiomatique est attendu par les concepteurs du langage, ce qui signifie que généralement ce code n'est pas seulement plus lisible, mais aussi plus efficace.

Obtenir un décompte

Même si vous n'avez pas besoin d'index au fur et à mesure, mais vous avez besoin d'un décompte des itérations (parfois souhaitables) avec lesquelles vous pouvez commencer 1 et le nombre final sera votre décompte.

for count, item in enumerate(items, start=1):   # default is zero
    print(item)

print('there were {0} items printed'.format(count))

Le compte semble être plus ce que vous avez l'intention de demander (par opposition à l'index) lorsque vous avez dit que vous vouliez de 1 à 5.


Décomposer - une explication étape par étape

Pour décomposer ces exemples, disons que nous avons une liste d'éléments que nous voulons répéter avec un index:

items = ['a', 'b', 'c', 'd', 'e']

Nous passons maintenant cet itérable à énumérer, créant un objet énuméré:

enumerate_object = enumerate(items) # the enumerate object

Nous pouvons retirer le premier élément de cet itérable que nous obtiendrions dans une boucle avec la nextfonction:

iteration = next(enumerate_object) # first iteration from enumerate
print(iteration)

Et nous voyons que nous obtenons un tuple 0, le premier index et 'a'le premier élément:

(0, 'a')

nous pouvons utiliser ce que l'on appelle le " décompression de séquence " pour extraire les éléments de ce double-tuple:

index, item = iteration
#   0,  'a' = (0, 'a') # essentially this.

et quand nous contrôlons index, nous trouvons qu'il est fait référence au premier indice, 0, et itemfait référence au premier élément, 'a'.

>>> print(index)
0
>>> print(item)
a

Conclusion

  • Les index Python commencent à zéro
  • Pour obtenir ces index à partir d'un itérable au fur et à mesure que vous le parcourez, utilisez la fonction énumération
  • L'utilisation d'énumération de manière idiomatique (avec le décompactage de tuple) crée un code plus lisible et plus facile à gérer:

Faites donc ceci:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)
Aaron Hall
la source
1
L'exemple " Obtention d'un décompte " fonctionne-t-il lorsqu'il itemsest vide?
Bergi
J'envoie des données en utilisant ajax aux vues Django sous forme de tableau sous la forme de deux valeurs dans une variable legData avec des valeurs comme [1406, 1409]. Si j'imprime sur la console à l'aide de print(legData), la sortie est [1406,1409] . Cependant, si j'essaie d'analyser les valeurs individuelles de la liste comme for idx, xLeg in enumerate(legData): print(idx, xLeg), cela m'obtient une sortie d'entiers individuels tels que [, 1, 4, 0, 6, etc. par rapport aux indices 0, 1, 2, 3, 4 etc. (oui, les crochets et les virgules sont également affichés comme s'ils faisaient partie des données elles-mêmes ). Qu'est-ce qui ne va pas ici?
user12379095
@ user12379095 vous avez probablement les données dans le mauvais type (une chaîne) et vous devez les convertir en une véritable liste de nombres au lieu d'une chaîne. C'est un peu hors sujet ici, veuillez supprimer votre commentaire et signaler le mien à supprimer comme n'étant plus nécessaire lorsque vous voyez cela.
Aaron Hall
153

Il est assez simple de le démarrer à partir 1de 0:

for index, item in enumerate(iterable, start=1):
   print index, item

Remarque

Astuce importante, bien qu'un peu trompeuse car indexsera un tuple (idx, item)ici. Bon à emporter.

UN J
la source
11
La question portait sur les index de liste; comme ils partent de 0, il ne sert à rien de partir d'un autre nombre car les index seraient faux (oui, le PO l'a dit aussi mal dans la question). Dans le cas contraire, l' appel de la variable qui est tuple index, itemjusteindex est très trompeur, comme vous l'avez noté. Utilisez simplement for index, item in enumerate(ints).
Antti Haapala
1
Mieux vaut enfermer l'index à l'intérieur des paires de parenthèses comme (index), cela fonctionnera à la fois sur les versions Python 2 et 3.
hygull
1
@AnttiHaapala La raison, je présume, est que la sortie attendue de la question commence à l'index 1 au lieu de 0
pushkin
90
for i in range(len(ints)):
   print i, ints[i]
David Hanak
la source
10
Cela devrait probablement être xrangepour la version antérieure à 3.0.
Ben Blank
44
Utilisez plutôt énumérer
saulspatz
3
Pour Python 2.3 ci-dessus, utilisez la fonction intégrée d'énumération car elle est plus Pythonic.
januarvs
Énumérer n'est pas toujours mieux - cela dépend des exigences de l'application. Dans ma situation actuelle, les relations entre les longueurs d'objets sont significatives pour mon application. Bien que j'ai commencé à utiliser l'énumération, je suis passé à cette approche pour éviter d'avoir à écrire une logique pour sélectionner l'objet à énumérer.
ADG
1
@adg Je ne vois pas comment éviter enumerateenregistre toute logique; vous devez toujours sélectionner avec quel objet indexer i, non?
chepner
47

Comme c'est la norme en Python, il existe plusieurs façons de le faire. Dans tous les exemples, supposez:lst = [1, 2, 3, 4, 5]

1. Utilisation d'énumérer ( considéré comme le plus idiomatique )

for index, element in enumerate(lst):
    # do the things that need doing here

C'est aussi l'option la plus sûre à mon avis car le risque d'entrer dans une récursion infinie a été éliminé. L'élément et son index sont tous deux contenus dans des variables et il n'est pas nécessaire d'écrire de code supplémentaire pour accéder à l'élément.

2. Création d'une variable pour contenir l'index (en utilisantfor )

for index in range(len(lst)):   # or xrange
    # you will have to write extra code to get the element

3. Création d'une variable pour contenir l'index (en utilisantwhile )

index = 0
while index < len(lst):
    # you will have to write extra code to get the element
    index += 1  # escape infinite recursion

4. Il y a toujours une autre façon

Comme expliqué précédemment, il existe d'autres moyens de le faire qui n'ont pas été expliqués ici et ils peuvent même s'appliquer davantage dans d'autres situations. par exemple en utilisant itertools.chainavec pour. Il gère mieux les boucles imbriquées que les autres exemples.

Charitoo
la source
30

Façon à l'ancienne:

for ix in range(len(ints)):
    print ints[ix]

Compréhension de la liste:

[ (ix, ints[ix]) for ix in range(len(ints))]

>>> ints
[1, 2, 3, 4, 5]
>>> for ix in range(len(ints)): print ints[ix]
... 
1
2
3
4
5
>>> [ (ix, ints[ix]) for ix in range(len(ints))]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> lc = [ (ix, ints[ix]) for ix in range(len(ints))]
>>> for tup in lc:
...     print tup
... 
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
>>> 
Charlie Martin
la source
3
Ce n'est pas faux et est utilisé en C / C ++ et autres. Il est considéré comme non pythonique, mais peut également être utilisé en python. Comme des solutions simples qui le décomposent à la source: +
Valor Naram
Certains extrémistes de python diraient, ne faites pas ça. Mais je l'ai dit seulement pour indiquer qu'il y a plus d'une façon possible
Valor Naram
21

Le moyen le plus rapide d'accéder aux index de la liste dans la boucle en Python 2.7 est d'utiliser la méthode range pour les petites listes et la méthode énumération pour les listes de taille moyenne et énorme.

Veuillez voir les différentes approches qui peuvent être utilisées pour parcourir la liste et accéder à la valeur d'index et leurs mesures de performance (qui, je suppose, vous seraient utiles) dans les exemples de code ci-dessous:

from timeit import timeit

# Using range
def range_loop(iterable):
    for i in range(len(iterable)):
        1 + iterable[i]

# Using xrange
def xrange_loop(iterable):
    for i in xrange(len(iterable)):
        1 + iterable[i]

# Using enumerate
def enumerate_loop(iterable):
    for i, val in enumerate(iterable):
        1 + val

# Manual indexing
def manual_indexing_loop(iterable):
    index = 0
    for item in iterable:
        1 + item
        index += 1

Voir les mesures de performances pour chaque méthode ci-dessous:

from timeit import timeit

def measure(l, number=10000):
print "Measure speed for list with %d items" % len(l)
print "xrange: ", timeit(lambda :xrange_loop(l), number=number)
print "range: ", timeit(lambda :range_loop(l), number=number)
print "enumerate: ", timeit(lambda :enumerate_loop(l), number=number)
print "manual_indexing: ", timeit(lambda :manual_indexing_loop(l), number=number)

measure(range(1000))
# Measure speed for list with 1000 items
# xrange:  0.758321046829
# range:  0.701184988022
# enumerate:  0.724966049194
# manual_indexing:  0.894635915756

measure(range(10000))
# Measure speed for list with 100000 items
# xrange:  81.4756360054
# range:  75.0172479153
# enumerate:  74.687623024
# manual_indexing:  91.6308541298

measure(range(10000000), number=100)
# Measure speed for list with 10000000 items
# xrange:  82.267786026
# range:  84.0493988991
# enumerate:  78.0344707966
# manual_indexing:  95.0491430759

En conséquence, l'utilisation de la rangeméthode est la plus rapide à répertorier avec 1000 éléments. Pour liste avec taille> 10 000 articlesenumerate c'est le gagnant.

Ajout de quelques liens utiles ci-dessous:

Andriy Ivaneyko
la source
5
"la lisibilité compte" La différence de vitesse dans la petite plage <1000 est insignifiante. Il est 3% plus lent sur une métrique de temps déjà petite.
Que diriez-vous de mettre à jour la réponse à Python 3?
Georgy
14

Tout d'abord, les index seront de 0 à 4. Les langages de programmation commencent à compter à partir de 0; n'oubliez pas cela ou vous rencontrerez une exception d'index hors limites. Tout ce dont vous avez besoin dans la boucle for est une variable comptant de 0 à 4 comme ceci:

for x in range(0, 5):

Gardez à l'esprit que j'ai écrit 0 à 5 car la boucle s'arrête un nombre avant le max. :)

Pour obtenir la valeur d'un index, utilisez

list[index]
ytpillai
la source
13

Voici ce que vous obtenez lorsque vous accédez à l'index en forboucles:

for i in enumerate(items): print(i)

items = [8, 23, 45, 12, 78]

for i in enumerate(items):
    print("index/value", i)

Résultat:

# index/value (0, 8)
# index/value (1, 23)
# index/value (2, 45)
# index/value (3, 12)
# index/value (4, 78)

for i, val in enumerate(items): print(i, val)

items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
    print("index", i, "for value", val)

Résultat:

# index 0 for value 8
# index 1 for value 23
# index 2 for value 45
# index 3 for value 12
# index 4 for value 78

for i, val in enumerate(items): print(i)

items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
    print("index", i)

Résultat:

# index 0
# index 1
# index 2
# index 3
# index 4
Andy
la source
12

Selon cette discussion: http://bytes.com/topic/python/answers/464012-objects-list-index

Itération du compteur de boucles

L'idiome actuel de bouclage sur les indices utilise la rangefonction intégrée:

for i in range(len(sequence)):
    # work with index i

La boucle sur les éléments et les indices peut être réalisée soit par l'ancien idiome, soit en utilisant la nouvelle zipfonction intégrée:

for i in range(len(sequence)):
    e = sequence[i]
    # work with index i and element e

ou

for i, e in zip(range(len(sequence)), sequence):
    # work with index i and element e

via http://www.python.org/dev/peps/pep-0212/

thinker007
la source
22
Cela ne fonctionnera pas pour l'itération via des générateurs. Utilisez simplement enumerate ().
Tadeck
De nos jours, l'idiome actuel est énuméré, pas l'appel de plage.
TankorSmash
et c'est la même chose que l'ancienne réponse: stackoverflow.com/a/522576/6451573
Jean-François Fabre
11

Vous pouvez le faire avec ce code:

ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
    index +=1
    print index, value

Utilisez ce code si vous devez réinitialiser la valeur d'index à la fin de la boucle:

ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
    index +=1
    print index, value
    if index >= len(ints)-1:
        index = 0
Liam
la source
10

La meilleure solution pour ce problème est l' utilisation Énumérer en fonction build python.
énumérer retour tuple
première valeur est index
deuxième valeur est élément de tableau à cet index

In [1]: ints = [8, 23, 45, 12, 78]

In [2]: for idx, val in enumerate(ints):
   ...:         print(idx, val)
   ...:     
(0, 8)
(1, 23)
(2, 45)
(3, 12)
(4, 78)
Anurag Misra
la source
9

Dans votre question, vous écrivez "comment accéder à l'index de boucle, de 1 à 5 dans ce cas?"

Cependant, l'index d'une liste s'exécute à partir de zéro. Nous devons donc savoir si ce que vous voulez réellement est l'index et l'élément pour chaque élément d'une liste, ou si vous voulez vraiment des nombres à partir de 1. Heureusement, en Python, il est facile de faire l'un ou les deux.

Tout d'abord, pour clarifier, la enumeratefonction renvoie de manière itérative l'index et l'élément correspondant pour chaque élément d'une liste.

alist = [1, 2, 3, 4, 5]

for n, a in enumerate(alist):
    print("%d %d" % (n, a))

La sortie de ce qui précède est alors,

0 1
1 2
2 3
3 4
4 5

Notez que l'index s'exécute à partir de 0. Ce type d'indexation est courant parmi les langages de programmation modernes, notamment Python et C.

Si vous souhaitez que votre boucle couvre une partie de la liste, vous pouvez utiliser la syntaxe Python standard pour une partie de la liste. Par exemple, pour effectuer une boucle à partir du deuxième élément d'une liste jusqu'au dernier élément, sans l'inclure, vous pouvez utiliser

for n, a in enumerate(alist[1:-1]):
    print("%d %d" % (n, a))

Notez qu'une fois encore, l'index de sortie va de 0,

0 2
1 3
2 4

Cela nous amène au start=ncommutateur pourenumerate() . Cela compense simplement l'index, vous pouvez simplement ajouter un nombre à l'index à l'intérieur de la boucle.

for n, a in enumerate(alist, start=1):
    print("%d %d" % (n, a))

dont la sortie est

1 1
2 2
3 3
4 4
5 5
DrM
la source
9

Si je nums = [1, 2, 3, 4, 5]devais répéter je ferais

for i, num in enumerate(nums, start=1):
    print(i, num)

Ou obtenez la longueur l = len(nums)

for i in range(l):
    print(i+1, nums[i])
Ankur Kothari
la source
7

S'il n'y a pas de valeur en double dans la liste:

for i in ints:
    indx = ints.index(i)
    print(i, indx)
RIshu
la source
1
Notez que la première option ne doit pas être utilisée, car elle ne fonctionne correctement que lorsque chaque élément de la séquence est unique.
Stam Kaly
2
La première option est O (n²), une idée terrible. Si votre liste contient 1 000 éléments, cela prendra littéralement 1 000 fois plus de temps que son utilisation enumerate. Vous devez supprimer cette réponse.
Boris
5

Vous pouvez également essayer ceci:

data = ['itemA.ABC', 'itemB.defg', 'itemC.drug', 'itemD.ashok']
x = []
for (i, item) in enumerate(data):
      a = (i, str(item).split('.'))
      x.append(a)
for index, value in x:
     print(index, value)

La sortie est

0 ['itemA', 'ABC']
1 ['itemB', 'defg']
2 ['itemC', 'drug']
3 ['itemD', 'ashok']
Ashok Kumar Jayaraman
la source
3

Vous pouvez utiliser la indexméthode

ints = [8, 23, 45, 12, 78]
inds = [ints.index(i) for i in ints]

EDIT Surligné dans le commentaire que cette méthode ne fonctionne pas s'il y a des doublons ints, la méthode ci-dessous devrait fonctionner pour toutes les valeurs de ints:

ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup[0] for tup in enumerate(ints)]

Ou bien

ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup for tup in enumerate(ints)]

si vous voulez obtenir à la fois l'index et la valeur dans intsune liste de tuples.

Il utilise la méthode de enumeratedans la réponse sélectionnée à cette question, mais avec une compréhension de la liste, ce qui le rend plus rapide avec moins de code.

PyRsquared
la source
2

Réponse simple en utilisant la boucle While:

arr = [8, 23, 45, 12, 78]
i = 0
while i<len(arr):
    print("Item ",i+1," = ",arr[i])
    i +=1

Production:

entrez la description de l'image ici

Amar Kumar
la source
1

Pour imprimer un tuple de (index, valeur) dans la compréhension de liste à l'aide d'une forboucle:

ints = [8, 23, 45, 12, 78]
print [(i,ints[i]) for i in range(len(ints))]

Production:

[(0, 8), (1, 23), (2, 45), (3, 12), (4, 78)]
lola
la source
1

Cela sert bien le but:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)
Sumit Kumar
la source
4
Cela se décomposera s'il y a des éléments répétés dans la liste, tout comme la index()recherche de la première occurrence de x, sans mentionner le temps O ( n ^ 2 ) requis pour rechercher chaque élément.
Peter Szoldan
totalement d'accord qu'il ne fonctionnera pas pour les éléments en double dans la liste. après tout, j'apprends aussi le python.
Sumit Kumar