Accedere all'indice nei cicli 'for'?


3607

Come posso accedere all'indice in un forciclo come il seguente?

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

Voglio ottenere questo risultato:

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

Quando lo eseguo in loop usando un forloop, come posso accedere all'indice del loop, da 1 a 5 in questo caso?


42
Nota che gli indici in Python iniziano da 0, quindi gli indici per il tuo elenco di esempi sono da 0 a 4 e non da 1 a 5
lavaggio del plug

Risposte:


6122

L'uso di una variabile di stato aggiuntiva, come una variabile di indice (che normalmente utilizzeresti in linguaggi come C o PHP), è considerato non pitonico.

L'opzione migliore è utilizzare la funzione integrata enumerate(), disponibile in Python 2 e 3:

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

Scopri PEP 279 per ulteriori informazioni.


61
Come Aaron indica di seguito, usa start = 1 se vuoi ottenere 1-5 invece di 0-4.
clozach,

2
Non enumeratecomporta un altro sovraccarico?
TheRealChx101,

@ TheRealChx101 secondo i miei test (Python 3.6.3) la differenza è trascurabile e talvolta anche a favore enumerate.
Błotosmętek,

806

Utilizzando un ciclo for, come posso accedere all'indice del ciclo, da 1 a 5 in questo caso?

Utilizzare enumerateper ottenere l'indice con l'elemento durante l'iterazione:

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

E nota che gli indici di Python iniziano da zero, quindi otterrai da 0 a 4 con quanto sopra. Se si desidera il conteggio, da 1 a 5, procedere come segue:

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

Flusso di controllo unidiomatico

Quello che stai chiedendo è l'equivalente Pythonic di quanto segue, che è l'algoritmo che la maggior parte dei programmatori di linguaggi di livello inferiore userebbe:

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 in lingue che non hanno un ciclo for-each:

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

o talvolta più comunemente (ma unidiomaticamente) trovato in Python:

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

Utilizzare la funzione di enumerazione

La enumeratefunzione di Python riduce il disordine visivo nascondendo la contabilità degli indici e incapsulando l'iterabile in un altro iterabile (un enumerateoggetto) che produce una tupla di due elementi dell'indice e l'elemento che l'iterable originale fornirebbe. Sembra così:

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

Questo esempio di codice è abbastanza bene l' esempio canonico della differenza tra il codice che è idiomatico di Python e il codice che non lo è. Il codice idiomatico è Python sofisticato (ma non complicato), scritto nel modo in cui doveva essere usato. Il codice idiomatico è previsto dai progettisti del linguaggio, il che significa che di solito questo codice non è solo più leggibile, ma anche più efficiente.

Ottenere un conteggio

Anche se non hai bisogno di indici mentre procedi, ma hai bisogno di un conteggio delle iterazioni (a volte desiderabili) puoi iniziare con 1e il numero finale sarà il tuo conteggio.

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

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

Il conteggio sembra essere più ciò che si intende chiedere (al contrario dell'indice) quando si afferma che si desidera da 1 a 5.


Abbattimento: una spiegazione dettagliata

Per scomporre questi esempi, supponiamo di avere un elenco di elementi che vogliamo ripetere con un indice:

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

Ora passiamo questo iterabile per enumerare, creando un oggetto enumerato:

enumerate_object = enumerate(items) # the enumerate object

Possiamo estrarre il primo elemento da questo iterabile che avremmo messo in loop con la nextfunzione:

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

E vediamo che otteniamo una tupla di 0, il primo indice e 'a'il primo elemento:

(0, 'a')

possiamo usare ciò che viene definito " decompressione della sequenza " per estrarre gli elementi da questa doppia tupla:

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

e quando abbiamo ispezionare index, troviamo si riferisce al primo indice, 0, e itemsi riferisce al primo elemento, 'a'.

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

Conclusione

  • Gli indici Python iniziano da zero
  • Per ottenere questi indici da un iterabile durante l'iterazione su di esso, utilizzare la funzione di enumerazione
  • L'uso dell'enumerazione in modo idiomatico (insieme al disimballaggio della tupla) crea un codice più leggibile e gestibile:

Quindi fai questo:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)

1
L'esempio " Ottenere un conteggio " funziona quando itemsè vuoto?
Bergi,

Sto inviando dati utilizzando Ajax alle viste Django come un array sotto forma di due valori in una legData variabile con valori come [1406, 1409]. Se stampo sulla console utilizzando print(legData), l'output è [1406,1409] . Tuttavia, se provo ad analizzare i singoli valori dell'elenco come for idx, xLeg in enumerate(legData): print(idx, xLeg), mi dà un output di singoli numeri interi come [, 1, 4, 0, 6 e così via contro gli indici 0, 1, 2, 3, 4 ecc. (sì, anche le parentesi quadre e la virgola vengono emesse come se fossero parte dei dati stessi ). Cosa non va qui?
user12379095,

@ user12379095 probabilmente hai i dati nel tipo sbagliato (una stringa) e devi convertirli in un vero elenco di numeri anziché in una stringa. Questo è un po 'fuori tema qui, per favore cancella il tuo commento e contrassegna il mio per essere eliminato come non più necessario quando vedi questo.
Aaron Hall

153

È abbastanza semplice avviarlo da 1altro 0:

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

Nota

Suggerimento importante, anche se un po 'fuorviante poiché indexsarà un tuple (idx, item)qui. Buono a partire.


11
La domanda riguardava gli indici delle liste; dal momento che iniziano da 0 c'è poco senso partire da un altro numero poiché gli indici sarebbero sbagliati (sì, anche l'OP ha detto che era sbagliato nella domanda). Altrimenti, chiamare la variabile che è tupla di index, itemjust indexè molto fuorviante, come hai notato. Basta usare for index, item in enumerate(ints).
Antti Haapala,

1
Meglio racchiudere l'indice all'interno delle coppie di parentesi come (indice), funzionerà su entrambe le versioni Python 2 e 3.
hygull

1
@AnttiHaapala Il motivo, presumo, è che l'output previsto della domanda inizia all'indice 1 anziché 0
pushkin

90
for i in range(len(ints)):
   print i, ints[i]

10
Probabilmente dovrebbe essere xrangeper pre-3.0.
Ben Blank,

44
Usa invece enumerate
saulspatz

3
Per Python 2.3 sopra, usa la funzione integrata enumerata poiché è più Pythonic.
gennaio

Enumerare non è sempre migliore, dipende dai requisiti dell'applicazione. Nella mia situazione attuale le relazioni tra le lunghezze degli oggetti sono significative per la mia applicazione. Sebbene abbia iniziato a utilizzare enumerate, sono passato a questo approccio per evitare di dover scrivere la logica per selezionare l'oggetto da enumerare.
adg

1
@adg Non vedo come evitare enumeratesalva qualsiasi logica; devi ancora selezionare con quale oggetto indicizzare i, no?
Chepner,

47

Come è la norma in Python ci sono diversi modi per farlo. In tutti gli esempi supponiamo:lst = [1, 2, 3, 4, 5]

1. Utilizzo dell'enumerato ( considerato il più idiomatico )

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

Questa è anche l'opzione più sicura secondo me perché è stata eliminata la possibilità di andare in ricorsione infinita. Sia l'articolo che il suo indice sono mantenuti in variabili e non è necessario scrivere ulteriori codici per accedere all'elemento.

2. Creazione di una variabile per contenere l'indice ( usandofor )

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

3. Creazione di una variabile per contenere l'indice ( usandowhile )

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

4. C'è sempre un altro modo

Come spiegato in precedenza, ci sono altri modi per farlo che non sono stati spiegati qui e potrebbero persino applicarsi di più in altre situazioni. ad es. usando itertools.chaincon per. Gestisce i loop nidificati meglio degli altri esempi.


30

Vecchio stile:

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

Comprensione elenco:

[ (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)
>>> 

3
Questo non è sbagliato ed è usato in C / C ++ e altri. È considerato non pythonic, ma può essere utilizzato anche in Python. Come semplici soluzioni che lo scompongono alla fonte: +
Valor Naram

Alcuni estremisti del pitone direbbero, non farlo. Ma l'ho detto solo per indicare che esiste più di un modo possibile
Valor Naram,

21

Il modo più rapido per accedere agli indici dell'elenco all'interno del loop in Python 2.7 è utilizzare il metodo range per elenchi di piccole dimensioni e il metodo di enumerazione per elenchi di medie e grandi dimensioni.

Si prega di vedere diversi approcci che possono essere utilizzati per scorrere l'elenco e accedere al valore dell'indice e alle relative metriche delle prestazioni (che suppongo possano essere utili per voi) negli esempi di codice seguenti:

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

Vedi le metriche delle prestazioni per ciascun metodo di seguito:

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

Di conseguenza, l'utilizzo del rangemetodo è il più veloce da elencare con 1000 voci. Per un elenco con dimensioni> 10 000 articoli enumerateè il vincitore.

Aggiunta di alcuni link utili di seguito:


5
"contabilità di lettura" La differenza di velocità nella gamma <1000 è insignificante. È più lento del 3% su una metrica di tempo già piccola.

Che ne dici di aggiornare la risposta a Python 3?
Georgy,

14

Prima di tutto, gli indici saranno da 0 a 4. I linguaggi di programmazione iniziano a contare da 0; non dimenticarlo o ti imbatterai in un indice fuori limite. Tutto ciò di cui hai bisogno nel ciclo for è una variabile che conta da 0 a 4 in questo modo:

for x in range(0, 5):

Tieni presente che ho scritto da 0 a 5 perché il ciclo si ferma un numero prima del massimo. :)

Per ottenere il valore di un indice utilizzare

list[index]

13

Ecco cosa ottieni quando accedi all'indice nei forloop:

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

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

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

Risultato:

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

Risultato:

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

Risultato:

# index 0
# index 1
# index 2
# index 3
# index 4

12

Secondo questa discussione: http://bytes.com/topic/python/answers/464012-objects-list-index

Loop iterazione contatore

L'attuale linguaggio per il loop degli indici fa uso della rangefunzione integrata:

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

Il looping su elementi e indici può essere ottenuto dal vecchio linguaggio o usando la nuova zipfunzione integrata:

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

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


22
Questo non funzionerà per iterare attraverso i generatori. Basta usare enumerate ().
Tadeck,

Al giorno d'oggi, il linguaggio corrente è enumerato, non la chiamata dell'intervallo.
TankorSmash

ed è la stessa della risposta precedente: stackoverflow.com/a/522576/6451573
Jean-François Fabre

11

Puoi farlo con questo codice:

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

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

Utilizzare questo codice se è necessario reimpostare il valore dell'indice alla fine 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

10

La migliore soluzione per questo problema è utilizzare la funzione enumerata in-build python.
enumera ritorno tupla
primo valore è indice
secondo valore è elemento dell'array in quell'indice

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)

9

Nella tua domanda scrivi "come posso accedere all'indice del loop, da 1 a 5 in questo caso?"

Tuttavia, l'indice per un elenco viene eseguito da zero. Quindi, allora abbiamo bisogno di sapere se quello che vuoi veramente è l'indice e l'elemento per ogni elemento in un elenco, o se vuoi davvero numeri a partire da 1. Fortunatamente, in Python, è facile fare uno o entrambi.

Innanzitutto, per chiarire, la enumeratefunzione restituisce iterativamente l'indice e l'elemento corrispondente per ciascun elemento in un elenco.

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

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

L'output per quanto sopra è quindi,

0 1
1 2
2 3
3 4
4 5

Si noti che l'indice viene eseguito da 0. Questo tipo di indicizzazione è comune tra i moderni linguaggi di programmazione tra cui Python e C.

Se si desidera che il ciclo si estenda su una parte dell'elenco, è possibile utilizzare la sintassi standard di Python per una parte dell'elenco. Ad esempio, per eseguire il ciclo dal secondo elemento in un elenco fino a ma non includendo l'ultimo elemento, è possibile utilizzare

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

Tieni presente che, ancora una volta, l'indice di output viene eseguito da 0,

0 2
1 3
2 4

Questo ci porta al start=npassaggio per enumerate(). Questo semplicemente compensa l'indice, puoi equivalentemente semplicemente aggiungere un numero all'indice all'interno del loop.

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

per cui l'output è

1 1
2 2
3 3
4 4
5 5

9

Se dovessi iterare, nums = [1, 2, 3, 4, 5]lo farei

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

O ottenere la lunghezza come l = len(nums)

for i in range(l):
    print(i+1, nums[i])

7

Se non esiste alcun valore duplicato nell'elenco:

for i in ints:
    indx = ints.index(i)
    print(i, indx)

1
Si noti che la prima opzione non deve essere utilizzata, poiché funziona correttamente solo quando ogni elemento nella sequenza è unico.
Stam Kaly,

2
La prima opzione è O (n²), un'idea terribile. Se la tua lista è lunga 1000 elementi, ci vorrà letteralmente 1000 volte più dell'uso enumerate. Devi eliminare questa risposta.
Boris,

5

Puoi anche provare questo:

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)

L'output è

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

3

Puoi usare il indexmetodo

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

EDIT Evidenziato nel commento che questo metodo non funziona se sono presenti duplicati ints, il metodo seguente dovrebbe funzionare per qualsiasi valore in ints:

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

O in alternativa

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

se si desidera ottenere sia l'indice che il valore intscome un elenco di tuple.

Utilizza il metodo di enumeratenella risposta selezionata a questa domanda, ma con la comprensione dell'elenco, rendendolo più veloce con meno codice.


2

Risposta semplice utilizzando While Loop:

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

Produzione:

inserisci qui la descrizione dell'immagine


1

Per stampare la tupla di (indice, valore) nella comprensione dell'elenco usando un forciclo:

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

Produzione:

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

1

Questo serve allo scopo abbastanza bene:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)

4
Questo si interromperà se ci sono elementi ripetuti nell'elenco come index()cercherà la prima occorrenza di x, senza menzionare il tempo O ( n ^ 2 ) richiesto per cercare ogni elemento.
Peter Szoldan,

concordato totalmente sul fatto che non funzionerà per elementi duplicati nell'elenco. dopotutto sto anche imparando Python.
Sumit Kumar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.