Uzyskujesz dostęp do indeksu w pętlach „for”?

3601

Jak uzyskać dostęp do indeksu w forpętli, jak poniżej?

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

Chcę uzyskać ten wynik:

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

Jak przejść przez pętlę za pomocą forpętli, jak uzyskać dostęp do indeksu pętli, od 1 do 5 w tym przypadku?

Joan Venge
źródło
42
Zauważ, że indeksy w pythonie zaczynają się od 0, więc indeksy dla twojej przykładowej listy wynoszą od 0 do 4, a nie od 1 do 5
płukanie

Odpowiedzi:

6107

Użycie dodatkowej zmiennej stanu, takiej jak zmienna indeksu (której normalnie używasz w językach takich jak C lub PHP), jest uważane za nie-pytoniczne.

Lepszą opcją jest użycie wbudowanej funkcji enumerate(), dostępnej zarówno w Pythonie 2, jak i 3:

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

Sprawdź PEP 279, aby uzyskać więcej.

Mike Hordecki
źródło
61
Jak podkreśla Aaron poniżej, użyj start = 1, jeśli chcesz dostać 1-5 zamiast 0-4.
clozach
2
Czy enumeratenie wiąże się to z dodatkowymi kosztami?
TheRealChx101
@ TheRealChx101 według moich testów (Python 3.6.3) różnica jest znikoma, a czasem nawet na korzyść enumerate.
Błotosmętek
804

Używając pętli for, jak uzyskać dostęp do indeksu pętli, od 1 do 5 w tym przypadku?

Użyj, enumerateaby uzyskać indeks z elementem podczas iteracji:

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

I zauważ, że indeksy Pythona zaczynają się od zera, więc otrzymałeś 0 do 4 z powyższym. Jeśli chcesz liczyć, od 1 do 5, zrób to:

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

Przepływ kontrolny Unidiomatic

To, o co prosisz, to Pythoniczny odpowiednik następującego, który jest algorytmem, którego większość programistów języków niższego poziomu użyłaby:

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

Lub w językach, w których nie ma pętli dla każdego:

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

lub czasem częściej (ale jednoznacznie) w Pythonie:

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

Użyj funkcji wyliczenia

enumerateFunkcja Pythona redukuje bałagan wizualny, ukrywając rozliczanie indeksów i zamykając iterowalny w innym iterowalnym ( enumerateobiekcie), który daje krotkę indeksu z dwoma pozycjami i element, który zapewni pierwotna iterowalna. To wygląda tak:

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

Ten przykład kodu jest dość dobrym kanonicznym przykładem różnicy między kodem, który jest idiomatyczny dla Pythona, a kodem, który nie jest. Kod idiomatyczny jest wyrafinowanym (ale nie skomplikowanym) Pythonem, napisanym w sposób, w jaki był przeznaczony do użycia. Kod idiomatyczny oczekuje od projektantów języka, co oznacza, że ​​zwykle ten kod jest nie tylko bardziej czytelny, ale także bardziej wydajny.

Uzyskiwanie rachunków

Nawet jeśli nie potrzebujesz indeksów na bieżąco, ale potrzebujesz liczby iteracji (czasem pożądanej), od której możesz zacząć, 1a ostateczna liczba będzie twoją liczbą.

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

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

Liczba wydaje się być bardziej, o co chcesz zapytać (w przeciwieństwie do indeksu), gdy powiedziałeś, że chcesz od 1 do 5.


Podział - wyjaśnienie krok po kroku

Aby rozbić te przykłady, powiedzmy, że mamy listę elementów, które chcemy iterować za pomocą indeksu:

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

Teraz przekazujemy iterowalną wartość do wyliczenia, tworząc obiekt wyliczeniowy:

enumerate_object = enumerate(items) # the enumerate object

Możemy wyciągnąć pierwszy element z iteracji, który dostalibyśmy w pętli z nextfunkcją:

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

Widzimy, że otrzymujemy krotkę 0pierwszego indeksu i 'a'pierwszego elementu:

(0, 'a')

możemy użyć tak zwanego „ rozpakowywania sekwencji ”, aby wyodrębnić elementy z tej dwu-krotki:

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

a kiedy sprawdzać index, uważamy, że odnosi się do pierwszego indeksu, 0, i itemodnosi się do pierwszego elementu, 'a'.

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

Wniosek

  • Indeksy języka Python zaczynają się od zera
  • Aby uzyskać te indeksy z iterowalnego podczas iteracji, użyj funkcji wyliczania
  • Użycie wyliczenia w sposób idiomatyczny (wraz z rozpakowaniem krotki) tworzy kod, który jest bardziej czytelny i łatwy do utrzymania:

Więc zrób to:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)
Aaron Hall
źródło
1
Czy przykład „ Pierwsze obliczenie ” działa, gdy itemsjest pusty?
Bergi
Przesyłam dane za pomocą ajax do widoków Django jako tablicę w postaci dwóch wartości w zmiennej legData o wartościach as [1406, 1409]. Jeśli drukuję na konsoli za pomocą print(legData), dane wyjściowe wynoszą [1406,1409] . Jeśli jednak spróbuję parsować poszczególne wartości z listy for idx, xLeg in enumerate(legData): print(idx, xLeg), otrzymam dane wyjściowe z poszczególnych liczb całkowitych, takich jak [, 1, 4, 0, 6 itd., Względem indeksów 0, 1, 2, 3, 4 itd. (tak, nawiasy kwadratowe i przecinek są również wyprowadzane, jakby były częścią samych danych ). Co tu idzie nie tak?
user12379095
@ user12379095 prawdopodobnie masz dane w niewłaściwym typie (ciąg znaków) i musisz przekonwertować je na rzeczywistą listę liczb zamiast ciągu. To trochę nie na temat, usuń swój komentarz i oznacz mój do usunięcia, ponieważ nie będzie już potrzebny, gdy to zobaczysz.
Aaron Hall
152

Uruchomienie go jest dość proste 1niż 0:

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

Uwaga

Ważna wskazówka, choć trochę myląca, ponieważ indexbędzie tuple (idx, item)tutaj. Dobrze iść.

AJ
źródło
11
Pytanie dotyczyło indeksów list; ponieważ zaczynają się od zera, nie ma sensu zaczynać od innej liczby, ponieważ indeksy byłyby błędne (tak, OP stwierdził również, że to źle w pytaniu). W przeciwnym razie wywołanie zmiennej, która jest krotką index, itemjust, indexjest bardzo mylące, jak zauważyłeś. Po prostu użyj for index, item in enumerate(ints).
Antti Haapala
1
Lepiej jest umieścić indeks w parach nawiasów jako (indeks), będzie on działał na obu wersjach Pythona 2 i 3.
hygull
1
@AnttiHaapala Powodem, jak przypuszczam, jest to, że oczekiwany wynik pytania zaczyna się od indeksu 1 zamiast 0
pushkin
90
for i in range(len(ints)):
   print i, ints[i]
David Hanak
źródło
10
Tak powinno być prawdopodobnie xrangew wersji wcześniejszej niż 3.0.
Ben Blank,
43
Zamiast tego użyj wyliczenia
saulspatz
3
W przypadku Python 2.3 powyżej użyj wbudowanej funkcji wyliczania, ponieważ jest ona bardziej Pythonic.
januarvs
Wyliczanie nie zawsze jest lepsze - zależy to od wymagań aplikacji. W mojej obecnej sytuacji relacje między długościami obiektów mają znaczenie dla mojej aplikacji. Mimo że zacząłem używać wyliczania, przełączyłem się na to podejście, aby uniknąć konieczności zapisywania logiki w celu wybrania obiektu do wyliczenia.
adg
1
@ adg Nie rozumiem, jak unikanie enumeratezapisuje jakąkolwiek logikę; nadal musisz wybrać obiekt, który chcesz indeksować i, nie?
chepner
47

Jak jest normą w Pythonie, jest na to kilka sposobów. We wszystkich przykładach założono:lst = [1, 2, 3, 4, 5]

1. Korzystanie z wyliczenia ( uważane za najbardziej idiomatyczne )

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

Moim zdaniem jest to również najbezpieczniejsza opcja, ponieważ wyeliminowano szansę na nieskończoną rekurencję. Zarówno element, jak i jego indeks są przechowywane w zmiennych i nie ma potrzeby pisania dalszego kodu, aby uzyskać dostęp do elementu.

2. Tworzenie zmiennej do przechowywania indeksu ( przy użyciufor )

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

3. Tworzenie zmiennej do przechowywania indeksu ( użyciewhile )

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

4. Zawsze jest inny sposób

Jak wyjaśniono wcześniej, istnieją inne sposoby, aby to zrobić, które nie zostały tu wyjaśnione, a mogą nawet zastosować więcej w innych sytuacjach. np. używając itertools.chainz. Obsługuje zagnieżdżone pętle lepiej niż inne przykłady.

Charitoo
źródło
30

Po staremu:

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

Zrozumienie listy:

[ (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
źródło
3
To nie jest złe i jest używane w C / C ++ i innych. Jest uważany za nie Pythonowy, ale może być również używany w Pythonie. Jak proste rozwiązania, które dzielą go na źródło: +
Valor Naram
Niektórzy ekstremiści python powiedzieliby: nie rób tego. Ale powiedziałem to tylko po to, aby wskazać, że jest więcej niż jeden możliwy sposób
Valor Naram
21

Najszybszym sposobem na uzyskanie dostępu do indeksów list w pętli w Pythonie 2.7 jest użycie metody range dla małych list i metody wyliczania dla list średnich i dużych.

Zapoznaj się z różnymi podejściami, które można zastosować do iteracji listy i dostępu do wartości indeksu oraz ich wskaźników wydajności (które, jak sądzę, byłyby dla Ciebie przydatne) w przykładach kodu poniżej:

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

Zobacz wskaźniki wydajności dla każdej metody poniżej:

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

W rezultacie użycie rangemetody jest najszybszą do listy z 1000 pozycji. Do listy o rozmiarze> 10 000 pozycjienumerateZwycięzcą jest .

Dodając kilka przydatnych linków poniżej:

Andrij Ivaneyko
źródło
5
„liczy się czytelność” Różnica prędkości w małym zakresie <1000 jest nieznaczna. Jest o 3% wolniejszy w i tak już krótkim czasie pomiaru.
Co powiesz na aktualizację odpowiedzi na Python 3?
Georgy
14

Po pierwsze, indeksy będą wynosić od 0 do 4. Języki programowania zaczną liczyć od 0; nie zapomnij o tym, bo znajdziesz wyjątek poza zakresem. Wszystko, czego potrzebujesz w pętli for, to zmienna zliczająca od 0 do 4, taka jak:

for x in range(0, 5):

Pamiętaj, że napisałem od 0 do 5, ponieważ pętla zatrzymuje jedną liczbę przed maksimum. :)

Aby uzyskać wartość indeksu użyj

list[index]
ytpillai
źródło
13

Oto, co dostajesz, gdy uzyskujesz dostęp do indeksu w forpętlach:

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

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

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

Wynik:

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

Wynik:

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

Wynik:

# index 0
# index 1
# index 2
# index 3
# index 4
Andy
źródło
12

Zgodnie z tą dyskusją: http://bytes.com/topic/python/answers/464012-objects-list-index

Przeciwdziałanie iteracji pętli

Bieżący idiom pętli nad indeksami wykorzystuje wbudowaną rangefunkcję:

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

Pętlę zarówno nad elementami, jak i indeksami można uzyskać za pomocą starego idiomu lub za pomocą nowej zipwbudowanej funkcji:

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

lub

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

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

thinker007
źródło
22
To nie zadziała w przypadku iteracji przez generatory. Wystarczy użyć enumerate ().
Tadeck
Obecnie obecny idiom jest wyliczony, a nie wywołanie zakresu.
TankorSmash,
i jest taki sam, jak starsza odpowiedź: stackoverflow.com/a/522576/6451573
Jean-François Fabre
11

Możesz to zrobić za pomocą tego kodu:

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

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

Użyj tego kodu, jeśli chcesz zresetować wartość indeksu na końcu pętli:

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
źródło
10

Najlepszym rozwiązaniem tego problemu jest użycie wbudowanej funkcji python w wyliczeniu .
wyliczyć zwracaną krotkę
pierwsza wartość to indeks
druga wartość to element tablicy o tym indeksie

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
źródło
9

W swoim pytaniu piszesz „jak uzyskać dostęp do indeksu pętli, w tym przypadku od 1 do 5?”

Jednak indeks listy zaczyna się od zera. Tak więc musimy wiedzieć, czy tak naprawdę potrzebujesz indeksu i elementu dla każdego elementu na liście, czy też naprawdę chcesz liczb zaczynających się od 1. Na szczęście w Pythonie łatwo jest wykonać jedno lub oba.

Po pierwsze, dla wyjaśnienia, enumeratefunkcja iteracyjnie zwraca indeks i odpowiedni element dla każdego elementu na liście.

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

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

Wynik dla powyższego jest wtedy,

0 1
1 2
2 3
3 4
4 5

Zauważ, że indeks zaczyna się od 0. Ten rodzaj indeksowania jest powszechny wśród współczesnych języków programowania, w tym Python i C.

Jeśli chcesz, aby twoja pętla obejmowała część listy, możesz użyć standardowej składni Pythona dla części listy. Na przykład, aby przejść od drugiego elementu na liście do ostatniego elementu, ale nie włączając go, możesz użyć

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

Zauważ, że po raz kolejny indeks wyjściowy zaczyna się od 0,

0 2
1 3
2 4

To prowadzi nas do start=nzmianyenumerate() . To po prostu równoważy indeks, możesz w równoważny sposób po prostu dodać liczbę do indeksu wewnątrz pętli.

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

dla którego wyjście jest

1 1
2 2
3 3
4 4
5 5
DrM
źródło
9

Gdybym miał wykonać iterację nums = [1, 2, 3, 4, 5], zrobiłbym to

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

Lub uzyskaj długość jako l = len(nums)

for i in range(l):
    print(i+1, nums[i])
Ankur Kothari
źródło
7

Jeśli na liście nie ma zduplikowanej wartości:

for i in ints:
    indx = ints.index(i)
    print(i, indx)
RIshu
źródło
1
Zauważ, że pierwsza opcja nie powinna być używana, ponieważ działa poprawnie tylko wtedy, gdy każdy element w sekwencji jest unikalny.
Stam Kaly
2
Pierwsza opcja to O (n²), okropny pomysł. Jeśli twoja lista ma 1000 elementów, potrwa dosłownie 1000 razy dłużej niż użycie enumerate. Powinieneś usunąć tę odpowiedź.
Boris,
5

Możesz także spróbować tego:

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)

Dane wyjściowe to

0 ['itemA', 'ABC']
1 ['itemB', 'defg']
2 ['itemC', 'drug']
3 ['itemD', 'ashok']
Ashok Kumar Jayaraman
źródło
3

Możesz użyć tej indexmetody

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

EDYCJA Podkreślone w komentarzu, że ta metoda nie działa, jeśli istnieją duplikaty ints, poniższa metoda powinna działać dla wszystkich wartości w ints:

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

Lub alternatywnie

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

jeśli chcesz uzyskać zarówno indeks, jak i wartość intsjako listę krotek.

Używa metody enumeratewybranej w odpowiedzi na to pytanie, ale ze zrozumieniem listy, dzięki czemu jest szybsza z mniejszym kodem.

PyRsquared
źródło
2

Prosta odpowiedź przy użyciu While Loop:

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

Wynik:

wprowadź opis zdjęcia tutaj

Amar Kumar
źródło
1

Aby wydrukować krotkę (indeksu, wartości) w rozumieniu listy za pomocą forpętli:

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

Wynik:

[(0, 8), (1, 23), (2, 45), (3, 12), (4, 78)]
Lola
źródło
1

Służy to celowi wystarczająco dobrze:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)
Sumit Kumar
źródło
4
To się rozpadnie, jeśli na liście są powtarzające się elementy, które index()będą szukać pierwszego wystąpienia x, nie wspominając o czasie O ( n ^ 2 ) wymaganym do wyszukania każdego elementu.
Peter Szoldan
całkowicie zgodził się, że nie będzie działać w przypadku zduplikowanych elementów na liście. w końcu uczę się również Pythona.
Sumit Kumar