Zugriff auf den Index in 'for'-Schleifen?

3605

Wie greife ich in einer forSchleife wie der folgenden auf den Index zu ?

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

Ich möchte diese Ausgabe erhalten:

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

forWie greife ich auf den Schleifenindex zu, wenn ich ihn mit einer Schleife durchlaufe , in diesem Fall von 1 bis 5?

Joan Venge
quelle
42
Beachten Sie, dass die Indizes in Python bei 0 beginnen, sodass die Indizes für Ihre Beispielliste 0 bis 4 und nicht 1 bis 5 sind
Plugwash

Antworten:

6116

Die Verwendung einer zusätzlichen Statusvariablen, z. B. einer Indexvariablen (die Sie normalerweise in Sprachen wie C oder PHP verwenden würden), wird als nicht pythonisch betrachtet.

Die bessere Option ist die Verwendung der integrierten Funktion enumerate(), die sowohl in Python 2 als auch in Python 3 verfügbar ist:

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

Weitere Informationen finden Sie in PEP 279 .

Mike Hordecki
quelle
61
Wie Aaron weiter unten ausführt, verwenden Sie start = 1, wenn Sie 1-5 anstelle von 0-4 erhalten möchten.
Clozach
2
Entsteht enumeratekein weiterer Aufwand?
TheRealChx101
@ TheRealChx101 nach meinen Tests (Python 3.6.3) ist der Unterschied vernachlässigbar und manchmal sogar zugunsten enumerate.
Błotosmętek
804

Wie greife ich mit einer for-Schleife auf den Schleifenindex zu, in diesem Fall von 1 bis 5?

Verwenden enumerateSie diese Option, um den Index mit dem Element abzurufen, während Sie iterieren:

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

Beachten Sie auch, dass die Python-Indizes bei Null beginnen, sodass Sie mit den oben genannten Werten 0 bis 4 erhalten. Wenn Sie die Zählung 1 bis 5 möchten, gehen Sie folgendermaßen vor:

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

Unidiomatischer Kontrollfluss

Was Sie verlangen, ist das pythonische Äquivalent des folgenden Algorithmus. Dies ist der Algorithmus, den die meisten Programmierer von Sprachen niedrigerer Ebenen verwenden würden:

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

Oder in Sprachen, die keine for-each-Schleife haben:

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

oder manchmal häufiger (aber unidiomatisch) in Python:

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

Verwenden Sie die Aufzählungsfunktion

Die enumerateFunktion von Python reduziert die visuelle Unordnung, indem die Berücksichtigung der Indizes ausgeblendet und das Iterable in ein anderes Iterable (ein enumerateObjekt) eingekapselt wird, das ein Tupel mit zwei Elementen des Index und des Elements ergibt, das das ursprüngliche Iterable bereitstellen würde. Das sieht so aus:

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

Dieses Codebeispiel ist ziemlich gut das kanonische Beispiel für den Unterschied zwischen Code, der für Python typisch ist, und Code, der nicht Python ist. Idiomatischer Code ist ausgefeiltes (aber nicht kompliziertes) Python, das so geschrieben wurde, wie es verwendet werden sollte. Von den Designern der Sprache wird idiomatischer Code erwartet, was bedeutet, dass dieser Code normalerweise nicht nur besser lesbar, sondern auch effizienter ist.

Eine Zählung bekommen

Auch wenn Sie unterwegs keine Indizes benötigen, aber eine Zählung der Iterationen (manchmal wünschenswert) benötigen, mit denen Sie beginnen können, 1und die endgültige Zahl ist Ihre Zählung.

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

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

Die Zählung scheint eher das zu sein, wonach Sie fragen möchten (im Gegensatz zum Index), als Sie sagten, Sie wollten von 1 bis 5.


Aufschlüsselung - eine schrittweise Erklärung

Angenommen, wir haben eine Liste von Elementen, die wir mit einem Index durchlaufen möchten, um diese Beispiele aufzuschlüsseln:

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

Jetzt übergeben wir diese Iterable an die Aufzählung und erstellen ein Aufzählungsobjekt:

enumerate_object = enumerate(items) # the enumerate object

Wir können das erste Element aus dieser Iterable herausziehen, das wir mit der nextFunktion in eine Schleife bekommen würden :

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

Und wir sehen, wir bekommen ein Tupel des 0ersten Index und 'a'des ersten Elements:

(0, 'a')

Wir können das, was als " Sequenzentpacken " bezeichnet wird, verwenden, um die Elemente aus diesem Zwei-Tupel zu extrahieren:

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

und wenn wir inspizieren index, stellen wir fest, dass es sich auf den ersten Index 0 und itemauf das erste Element bezieht 'a'.

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

Fazit

  • Python-Indizes beginnen bei Null
  • Verwenden Sie die Aufzählungsfunktion, um diese Indizes von einer Iterable abzurufen, während Sie darüber iterieren
  • Durch die idiomatische Verwendung von enumerate (zusammen mit dem Entpacken von Tupeln) wird Code erstellt, der besser lesbar und wartbar ist:

Also mach das:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)
Aaron Hall
quelle
1
Funktioniert das Beispiel " Eine Zählung erhalten ", wenn itemses leer ist?
Bergi
Ich sende Daten mit Ajax an Django-Ansichten als Array in Form von zwei Werten in einer Variablen legData mit den Werten as [1406, 1409]. Wenn ich mit auf die Konsole druckeprint(legData) , lautet die Ausgabe [1406,1409] . Wenn ich jedoch versuche, die einzelnen Werte der Liste wie folgt zu analysieren for idx, xLeg in enumerate(legData): print(idx, xLeg), erhalte ich eine Ausgabe einzelner Ganzzahlen wie [, 1, 4, 0, 6 usw. gegen die Indizes 0, 1, 2, 3, 4 usw. (ja, die eckigen Klammern und Kommas werden ebenfalls ausgegeben, als wären sie Teil der Daten selbst ). Was läuft hier falsch?
user12379095
@ user12379095 Sie haben wahrscheinlich die Daten im falschen Typ (eine Zeichenfolge) und müssen sie in eine tatsächliche Liste von Zahlen anstelle einer Zeichenfolge konvertieren. Das ist hier etwas unangebracht. Bitte löschen Sie Ihren Kommentar und markieren Sie meinen als zu löschen, wenn Sie dies sehen.
Aaron Hall
152

Es ist ziemlich einfach, es 1anders zu starten als 0:

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

Hinweis

Wichtiger Hinweis, wenn auch ein wenig irreführend, da indexwird hier ein tuple (idx, item). Gut zu gehen.

AJ
quelle
11
Die Frage betraf Listenindizes; Da sie bei 0 beginnen, macht es wenig Sinn, von einer anderen Zahl auszugehen, da die Indizes falsch wären (ja, das OP hat dies auch in der Frage falsch gesagt). Andernfalls wird die Variable aufrufen , die Tupel ist index, itemnur indexsehr irreführend, da man zur Kenntnis genommen. Einfach benutzen for index, item in enumerate(ints).
Antti Haapala
1
Besser ist es, den Index in Klammerpaare als (Index)
einzuschließen. Dies
1
@AnttiHaapala Der Grund, nehme ich an, ist, dass die erwartete Ausgabe der Frage bei Index 1 statt 0 beginnt
Puschkin
90
for i in range(len(ints)):
   print i, ints[i]
David Hanak
quelle
10
Das sollte wohl xrangefür Pre-3.0 sein.
Ben Blank
43
Verwenden Sie stattdessen Aufzählung
saulspatz
3
Verwenden Sie für Python 2.3 oben die integrierte Aufzählungsfunktion, da es mehr Pythonic ist.
Januarvs
Aufzählen ist nicht immer besser - es hängt von den Anforderungen der Anwendung ab. In meiner aktuellen Situation sind die Beziehungen zwischen den Objektlängen für meine Anwendung von Bedeutung. Obwohl ich anfing, Enumerate zu verwenden, wechselte ich zu diesem Ansatz, um zu vermeiden, dass ich Logik schreiben muss, um das aufzuzählende Objekt auszuwählen.
Adg
1
@adg Ich sehe nicht, wie vermeide es, enumerateLogik zu speichern. Sie müssen noch auswählen, mit welchem ​​Objekt indiziert werden soll i, nein?
Chepper
47

Wie es in Python üblich ist, gibt es verschiedene Möglichkeiten, dies zu tun. In allen Beispielen wird angenommen:lst = [1, 2, 3, 4, 5]

1. Aufzählung verwenden ( als am idiomatischsten angesehen )

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

Dies ist meiner Meinung nach auch die sicherste Option, da die Möglichkeit einer unendlichen Rekursion ausgeschlossen ist. Sowohl das Element als auch sein Index werden in Variablen gespeichert, und es ist nicht erforderlich, weiteren Code zu schreiben, um auf das Element zuzugreifen.

2. Erstellen einer Variablen für den Index ( usingfor )

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

3. Erstellen einer Variablen für den Index ( usingwhile )

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

4. Es gibt immer einen anderen Weg

Wie bereits erläutert, gibt es andere Möglichkeiten, die hier nicht erläutert wurden, und sie können in anderen Situationen sogar noch häufiger angewendet werden. zB unter Verwendung von itertools.chainmit für. Es verarbeitet verschachtelte Schleifen besser als die anderen Beispiele.

Charitoo
quelle
30

Unmodern:

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

Listenverständnis:

[ (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
quelle
3
Dies ist nicht falsch und wird in C / C ++ und anderen verwendet. Es wird als nicht pythonisch angesehen, kann aber auch in Python verwendet werden. Wie einfache Lösungen, die es bis zur Quelle
Valor Naram
Einige Python- Extremisten würden sagen, tu das nicht. Aber ich sagte es nur, um anzuzeigen, dass es mehr als einen möglichen Weg gibt
Valor Naram
21

Der schnellste Weg, um auf Listenindizes innerhalb der Schleife in Python 2.7 zuzugreifen, besteht darin, die Bereichsmethode für kleine Listen und die Aufzählungsmethode für Listen mittlerer und großer Größe zu verwenden.

In den folgenden Codebeispielen finden Sie verschiedene Ansätze , die zum Durchlaufen des Listen- und Zugriffsindexwerts und ihrer Leistungsmetriken (die für Sie nützlich sein könnten) verwendet werden können:

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

Siehe Leistungsmetriken für jede Methode unten:

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

Infolgedessen ist die Verwendung der rangeMethode mit 1000 Elementen die schnellste bis zur Liste. Für eine Liste mit einer Größe von> 10 000 Artikeln enumerateist der Gewinner.

Fügen Sie unten einige nützliche Links hinzu:

Andriy Ivaneyko
quelle
5
"Lesbarkeit zählt" Der Geschwindigkeitsunterschied im kleinen Bereich <1000 ist unbedeutend. Bei einer bereits kleinen Zeitmetrik ist sie 3% langsamer.
Wie wäre es mit einem Update der Antwort auf Python 3?
Georgy
14

Zuallererst werden die Indizes von 0 bis 4 sein. Programmiersprachen beginnen mit dem Zählen von 0; Vergessen Sie das nicht, sonst stoßen Sie auf einen Index außerhalb der Grenzen. Alles, was Sie in der for-Schleife benötigen, ist eine Variable, die wie folgt von 0 bis 4 zählt:

for x in range(0, 5):

Denken Sie daran, dass ich 0 bis 5 geschrieben habe, da die Schleife eine Zahl vor dem Maximum stoppt. :) :)

Um den Wert eines Index zu erhalten, verwenden Sie

list[index]
ytpillai
quelle
13

Folgendes erhalten Sie, wenn Sie in forSchleifen auf den Index zugreifen :

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

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

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

Ergebnis:

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

Ergebnis:

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

Ergebnis:

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

Nach dieser Diskussion: http://bytes.com/topic/python/answers/464012-objects-list-index

Iteration des Schleifenzählers

Die aktuelle Sprache zum Durchlaufen der Indizes verwendet die integrierte rangeFunktion:

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

Das Durchlaufen von Elementen und Indizes kann entweder durch die alte Sprache oder durch Verwendung der neuen zipintegrierten Funktion erreicht werden:

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

oder

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

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

thinker007
quelle
22
Dies funktioniert nicht beim Durchlaufen von Generatoren. Verwenden Sie einfach enumerate ().
Tadeck
Heutzutage ist die aktuelle Redewendung Aufzählung, nicht der Bereichsaufruf.
TankorSmash
und es ist das gleiche wie die ältere Antwort: stackoverflow.com/a/522576/6451573
Jean-François Fabre
11

Sie können es mit diesem Code tun:

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

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

Verwenden Sie diesen Code, wenn Sie den Indexwert am Ende der Schleife zurücksetzen müssen:

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

Die beste Lösung für dieses Problem ist die Aufzählung der eingebauten Python-Funktion.
Aufzählen return Tupels
erster Wert index
zweiter Wert Element des Arrays an diesem 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
quelle
9

In Ihrer Frage schreiben Sie: "Wie greife ich auf den Schleifenindex zu, in diesem Fall von 1 bis 5?"

Der Index für eine Liste läuft jedoch von Null. Dann müssen wir wissen, ob Sie tatsächlich den Index und das Element für jedes Element in einer Liste möchten oder ob Sie wirklich Zahlen ab 1 möchten. Glücklicherweise ist es in Python einfach, eines oder beide zu tun.

Zur Verdeutlichung gibt die enumerateFunktion zunächst iterativ den Index und das entsprechende Element für jedes Element in einer Liste zurück.

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

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

Die Ausgabe für das Obige ist dann,

0 1
1 2
2 3
3 4
4 5

Beachten Sie, dass der Index von 0 ausgeht. Diese Art der Indizierung ist in modernen Programmiersprachen wie Python und C üblich.

Wenn Ihre Schleife einen Teil der Liste umfassen soll, können Sie die Standard-Python-Syntax für einen Teil der Liste verwenden. Sie können beispielsweise eine Schleife vom zweiten Element in einer Liste bis zum letzten Element, jedoch ohne dieses, verwenden

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

Beachten Sie, dass der Ausgabeindex erneut von 0 läuft.

0 2
1 3
2 4

Das bringt uns zum start=nSchalter für enumerate(). Dadurch wird der Index einfach ausgeglichen. Sie können dem Index innerhalb der Schleife auch einfach eine Zahl hinzufügen.

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

für die die Ausgabe ist

1 1
2 2
3 3
4 4
5 5
DrM
quelle
9

Wenn ich iterieren nums = [1, 2, 3, 4, 5]würde, würde ich es tun

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

Oder erhalten Sie die Länge als l = len(nums)

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

Wenn die Liste keinen doppelten Wert enthält:

for i in ints:
    indx = ints.index(i)
    print(i, indx)
RIshu
quelle
1
Beachten Sie, dass die erste Option nicht verwendet werden sollte, da sie nur dann ordnungsgemäß funktioniert, wenn jedes Element in der Sequenz eindeutig ist.
Stam Kaly
2
Die erste Option ist O (n²), eine schreckliche Idee. Wenn Ihre Liste 1000 Elemente lang ist, dauert sie buchstäblich 1000-mal länger als die Verwendung enumerate. Sie sollten diese Antwort löschen.
Boris
5

Sie können dies auch versuchen:

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)

Die Ausgabe ist

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

Sie können die indexMethode verwenden

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

BEARBEITEN In dem Kommentar hervorgehoben, dass diese Methode nicht funktioniert, wenn Duplikate vorhanden sind ints, sollte die folgende Methode für alle Werte in funktionieren ints:

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

Oder alternativ

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

Wenn Sie sowohl den Index als auch den Wert intsals Liste von Tupeln erhalten möchten .

Es verwendet die Methode von enumeratein der ausgewählten Antwort auf diese Frage, jedoch mit Listenverständnis, wodurch es mit weniger Code schneller wird.

PyRsquared
quelle
2

Einfache Antwort mit While Loop:

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

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Amar Kumar
quelle
1

So drucken Sie ein Tupel (Index, Wert) im Listenverständnis mit einer forSchleife:

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

Ausgabe:

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

Dies erfüllt den Zweck gut genug:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)
Sumit Kumar
quelle
4
Dies wird zusammenbrechen, wenn die Liste wiederholte Elemente enthält, und es index()wird nach dem ersten Auftreten von gesucht x, ganz zu schweigen von der O ( n ^ 2 ) -Zeit, die zum Nachschlagen jedes Elements erforderlich ist.
Peter Szoldan
Ich bin völlig einverstanden, dass es nicht für doppelte Elemente in der Liste funktioniert. Immerhin lerne ich auch Python.
Sumit Kumar