¿Accediendo al índice en bucles 'for'?

3607

¿Cómo accedo al índice en un forbucle como el siguiente?

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

Quiero obtener esta salida:

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

Cuando lo recorro usando un forbucle, ¿cómo accedo al índice del bucle, de 1 a 5 en este caso?

Joan Venge
fuente
42
Tenga en cuenta que los índices en Python comienzan desde 0, por lo que los índices para su lista de ejemplo son 0 a 4, no 1 a 5
plugwash

Respuestas:

6122

El uso de una variable de estado adicional, como una variable de índice (que normalmente usaría en lenguajes como C o PHP), se considera no pitónico.

La mejor opción es utilizar la función integrada enumerate(), disponible en Python 2 y 3:

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

Echa un vistazo a PEP 279 para más.

Mike Hordecki
fuente
61
Como Aaron señala a continuación, use start = 1 si desea obtener 1-5 en lugar de 0-4.
clozach
2
¿ enumerateNo incurre en otra sobrecarga?
TheRealChx101
@ TheRealChx101 según mis pruebas (Python 3.6.3) la diferencia es insignificante y, a veces, incluso a favor enumerate.
Błotosmętek
806

Usando un bucle for, ¿cómo accedo al índice del bucle, de 1 a 5 en este caso?

Use enumeratepara obtener el índice con el elemento a medida que itera:

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

Y tenga en cuenta que los índices de Python comienzan en cero, por lo que obtendría 0 a 4 con lo anterior. Si desea el recuento del 1 al 5, haga esto:

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

Flujo de control unidiomático

Lo que está pidiendo es el equivalente pitónico de lo siguiente, que es el algoritmo que usarían la mayoría de los programadores de lenguajes de nivel inferior:

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

O en idiomas que no tienen un ciclo for-each:

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

o a veces más comúnmente (pero unidiomáticamente) encontrado en Python:

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

Use la función Enumerar

La enumeratefunción de Python reduce el desorden visual al ocultar la contabilidad de los índices y encapsular el iterable en otro iterable (un enumerateobjeto) que produce una tupla de dos elementos del índice y el elemento que proporcionaría el iterable original. Eso se ve así:

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

Este ejemplo de código es bastante bien el ejemplo canónico de la diferencia entre el código que es idiomático de Python y el código que no lo es. El código idiomático es Python sofisticado (pero no complicado), escrito de la manera en que estaba destinado a ser utilizado. Los diseñadores del lenguaje esperan un código idiomático, lo que significa que generalmente este código no solo es más legible, sino también más eficiente.

Obtener un conteo

Incluso si no necesita índices a medida que avanza, pero necesita un recuento de las iteraciones (a veces deseable) con las que puede comenzar 1y el número final será su recuento.

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

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

El recuento parece ser más de lo que pretendes pedir (en lugar del índice) cuando dijiste que querías del 1 al 5.


Desglosándolo: una explicación paso a paso

Para desglosar estos ejemplos, digamos que tenemos una lista de elementos que queremos iterar con un índice:

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

Ahora pasamos este iterable para enumerar, creando un objeto de enumeración:

enumerate_object = enumerate(items) # the enumerate object

Podemos extraer el primer elemento de este iterable que obtendríamos en un bucle con la nextfunción:

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

Y vemos que obtenemos una tupla del 0primer índice y 'a'del primer elemento:

(0, 'a')

podemos usar lo que se conoce como " desempaquetado de secuencia " para extraer los elementos de esta tupla doble:

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

y cuando inspeccionamos index, encontramos que se refiere al primer índice, 0, y itemse refiere al primer punto, 'a'.

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

Conclusión

  • Los índices de Python comienzan en cero
  • Para obtener estos índices de un iterable a medida que itera sobre él, use la función de enumeración
  • El uso de enumerar de forma idiomática (junto con el desempaquetado de tuplas) crea un código que es más legible y mantenible:

Entonces haz esto:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)
Aaron Hall
fuente
1
¿ Funciona el ejemplo " Obtener un recuento " cuando itemsestá vacío?
Bergi
Estoy enviando datos usando ajax a las vistas de Django como una matriz en forma de dos valores en una variable legData con valores como [1406, 1409]. Si imprimo en la consola usando print(legData), la salida es [1406,1409] . Sin embargo, si trato de analizar los valores individuales de la lista como for idx, xLeg in enumerate(legData): print(idx, xLeg), me da una salida de enteros individuales como [, 1, 4, 0, 6, y así sucesivamente contra los índices 0, 1, 2, 3, 4 etc. (sí, los corchetes y la coma también se muestran como si fueran parte de los datos ). ¿Qué está mal aquí?
user12379095
@ user12379095 probablemente tenga los datos en el tipo incorrecto (una cadena) y necesite convertirlos en una lista real de números en lugar de una cadena. Eso es algo fuera de tema aquí, borre su comentario y marque el mío para que se elimine, ya que ya no es necesario cuando vea esto.
Aaron Hall
153

Es bastante simple iniciarlo desde 1otro que no sea 0:

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

Nota

Sugerencia importante, aunque un poco engañosa ya indexque será un tuple (idx, item)aquí. Bueno para ir.

AJ
fuente
11
La pregunta era sobre índices de listas; dado que comienzan desde 0, no tiene mucho sentido comenzar desde otro número ya que los índices estarían equivocados (sí, el OP también lo dijo mal en la pregunta). De lo contrario, llamar a la variable tupla de index, itemjust indexes muy engañoso, como notó. Solo úsalo for index, item in enumerate(ints).
Antti Haapala
1
Mejor es encerrar el índice dentro de los pares de paréntesis como (index), funcionará tanto en las versiones 2 y 3. de
Python
1
@AnttiHaapala La razón, supongo, es que la salida esperada de la pregunta comienza en el índice 1 en lugar de 0
pushkin
90
for i in range(len(ints)):
   print i, ints[i]
David Hanak
fuente
10
Eso probablemente debería ser xrangepara pre-3.0.
Ben Blank
44
Use enumerate en su lugar
saulspatz
3
Para Python 2.3 anterior, use la función incorporada enumerate ya que es más Pythonic.
januarvs
Enumerar no siempre es mejor, depende de los requisitos de la aplicación. En mi situación actual, las relaciones entre las longitudes de los objetos son significativas para mi aplicación. Aunque comencé a usar enumerate, cambié a este enfoque para evitar tener que escribir lógica para seleccionar qué objeto enumerar.
Adg
1
@adg No veo cómo evitar enumerateguarda ninguna lógica; todavía tiene que seleccionar con qué objeto indexar i, ¿no?
chepner
47

Como es la norma en Python, hay varias formas de hacerlo. En todos los ejemplos, suponga:lst = [1, 2, 3, 4, 5]

1. Usando enumerate ( considerado el más idiomático )

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

Esta es también la opción más segura en mi opinión porque se ha eliminado la posibilidad de entrar en una recursión infinita. Tanto el elemento como su índice se mantienen en variables y no hay necesidad de escribir ningún código adicional para acceder al elemento.

2. Crear una variable para contener el índice ( usandofor )

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

3. Crear una variable para contener el índice ( usandowhile )

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

4. Siempre hay otra forma

Como se explicó anteriormente, hay otras formas de hacer esto que no se han explicado aquí e incluso pueden aplicarse más en otras situaciones. por ejemplo, usar itertools.chaincon for. Maneja los bucles anidados mejor que los otros ejemplos.

Charitoo
fuente
30

De forma anticuada:

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

Lista de comprensión:

[ (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
fuente
3
Esto no está mal y se usa en C / C ++ y otros. Se considera no pitónico, pero también se puede usar en python. Como soluciones simples que lo desglosan en la fuente: +
Valor Naram
Algunos extremistas de Python dirían, no hagas esto. Pero lo dije solo para indicar que hay más de una forma posible
Valor Naram el
21

La forma más rápida de acceder a los índices de la lista dentro del bucle en Python 2.7 es usar el método de rango para listas pequeñas y el método de enumeración para listas de tamaño medio y grande.

Vea los diferentes enfoques que se pueden usar para iterar sobre el valor de la lista y el índice de acceso y sus métricas de rendimiento (que supongo que serían útiles para usted) en los ejemplos de código a continuación:

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

Consulte las métricas de rendimiento para cada método a continuación:

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

Como resultado, usar el rangemétodo es el más rápido hasta la lista con 1000 elementos. Para la lista con tamaño> 10 000 artículos enumeratees el ganador.

Agregando algunos enlaces útiles a continuación:

Andriy Ivaneyko
fuente
55
"la legibilidad cuenta" La diferencia de velocidad en el rango pequeño <1000 es insignificante. Es un 3% más lento en una métrica de tiempo ya pequeña.
¿Qué tal actualizar la respuesta a Python 3?
Georgy
14

En primer lugar, los índices serán de 0 a 4. Los lenguajes de programación comienzan a contar desde 0; no lo olvide o encontrará una excepción de índice fuera de límites. Todo lo que necesita en el bucle for es un recuento variable de 0 a 4, así:

for x in range(0, 5):

Tenga en cuenta que escribí 0 a 5 porque el ciclo se detiene un número antes del máximo. :)

Para obtener el valor de un índice use

list[index]
Ytpillai
fuente
13

Esto es lo que obtienes cuando accedes al índice en forbucles:

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

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

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

Resultado:

# 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)

Resultado:

# 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)

Resultado:

# index 0
# index 1
# index 2
# index 3
# index 4
Andy
fuente
12

De acuerdo con esta discusión: http://bytes.com/topic/python/answers/464012-objects-list-index

Iteración de contador de bucle

El idioma actual para recorrer los índices hace uso de la rangefunción incorporada:

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

El bucle sobre ambos elementos e índices puede lograrse ya sea por el viejo idioma o mediante el uso de la nueva zipfunción incorporada:

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

o

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

a través de http://www.python.org/dev/peps/pep-0212/

pensador007
fuente
22
Esto no funcionará para iterar a través de generadores. Solo usa enumerate ().
Tadeck
Hoy en día, el idioma actual es enumerar, no la llamada de rango.
TankorSmash
y es lo mismo que la respuesta anterior: stackoverflow.com/a/522576/6451573
Jean-François Fabre
11

Puedes hacerlo con este código:

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

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

Use este código si necesita restablecer el valor del índice al final del ciclo:

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
fuente
10

La mejor solución para este problema es utilizar la función enumerar Python incorporada.
enumerar retorno tupla
primer valor es índice
segundo valor es elemento de la matriz en ese índice

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
fuente
9

En su pregunta, escribe "¿cómo accedo al índice de bucle, de 1 a 5 en este caso?"

Sin embargo, el índice de una lista se ejecuta desde cero. Entonces, debemos saber si lo que realmente desea es el índice y el elemento para cada elemento de una lista, o si realmente desea números que comiencen desde 1. Afortunadamente, en Python, es fácil hacer uno o ambos.

Primero, para aclarar, la enumeratefunción devuelve iterativamente el índice y el elemento correspondiente para cada elemento en una lista.

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

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

La salida para lo anterior es entonces,

0 1
1 2
2 3
3 4
4 5

Observe que el índice se ejecuta desde 0. Este tipo de indexación es común entre los lenguajes de programación modernos, incluidos Python y C.

Si desea que su ciclo abarque una parte de la lista, puede usar la sintaxis estándar de Python para una parte de la lista. Por ejemplo, para recorrer desde el segundo elemento de una lista hasta el último elemento, pero sin incluirlo, puede usar

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

Tenga en cuenta que, una vez más, el índice de salida se ejecuta desde 0,

0 2
1 3
2 4

Eso nos lleva al start=ncambio de enumerate(). Esto simplemente compensa el índice, de manera equivalente puede simplemente agregar un número al índice dentro del bucle.

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

para el cual la salida es

1 1
2 2
3 3
4 4
5 5
DrM
fuente
9

Si nums = [1, 2, 3, 4, 5]tuviera que repetir , lo haría

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

O obtener la longitud como l = len(nums)

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

Si no hay un valor duplicado en la lista:

for i in ints:
    indx = ints.index(i)
    print(i, indx)
Rshu
fuente
1
Tenga en cuenta que la primera opción no debe usarse, ya que solo funciona correctamente solo cuando cada elemento de la secuencia es único.
Stam Kaly
2
La primera opción es O (n²), una idea terrible. Si su lista tiene 1000 elementos, tomará literalmente 1000 veces más que usarla enumerate. Deberías eliminar esta respuesta.
Boris
5

También puedes probar esto:

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 salida es

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

Puedes usar el indexmétodo

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

EDITAR Destacado en el comentario de que este método no funciona si hay duplicados ints, el siguiente método debería funcionar para cualquier valor en ints:

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

O alternativamente

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

si desea obtener tanto el índice como el valor intscomo una lista de tuplas.

Utiliza el método de enumerateen la respuesta seleccionada a esta pregunta, pero con comprensión de la lista, lo que lo hace más rápido con menos código.

PyRsquared
fuente
2

Respuesta simple usando el bucle While:

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

Salida:

ingrese la descripción de la imagen aquí

Amar Kumar
fuente
1

Para imprimir la tupla de (índice, valor) en la comprensión de la lista usando un forbucle:

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

Salida:

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

Esto sirve el propósito lo suficientemente bien:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)
Sumit Kumar
fuente
44
Esto se desglosará si hay elementos repetidos en la lista, ya index()que buscará la primera aparición de x, sin mencionar el tiempo O ( n ^ 2 ) requerido para buscar cada elemento.
Peter Szoldan
Totalmente de acuerdo en que no funcionará para elementos duplicados en la lista. Después de todo, también estoy aprendiendo Python.
Sumit Kumar