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?


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.


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)

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ść.


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]

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.


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

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:


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]

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

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/


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

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)

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

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

7

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

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

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']

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.


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


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

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)

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.