Pytanie Dostęp do indeksu w pętlach 'for'?


Jak uzyskać dostęp do samego indeksu dla listy podobnej do poniższej?

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

Kiedy przechodzę przez to za pomocą a for pętli, jak mam uzyskać dostęp do indeksu pętli, w tym przypadku od 1 do 5?


2563
2018-02-06 22:47


pochodzenie




Odpowiedzi:


Używanie dodatkowej zmiennej stanu, takiej jak zmienna indeksowa (którą normalnie używasz w językach takich jak C lub PHP), jest uważane za niezwiązane z pythonami.

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

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

Sprawdzić PEP 279 więcej.


4456
2018-02-06 22:52



Jak wskazuje Aaron poniżej, użyj start = 1, jeśli chcesz uzyskać 1-5 zamiast 0-4. - clozach


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

Posługiwać się enumerate aby uzyskać indeks z elementem podczas iteracji:

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

Zauważ, że indeksy Pythona zaczynają się od zera, więc otrzymasz od 0 do 4 z powyższym. Jeśli chcesz liczyć, od 1 do 5, wykonaj następujące czynności:

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

Unidiomatyczny przepływ sterowania

To, o co prosisz, to odpowiednik Pythononu, który jest algorytmem używanym przez większość programistów języków niższego poziomu:

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, które nie mają pętli for-each:

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

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

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

Użyj funkcji wyliczenia

Python enumerate funkcjonować zmniejsza bałagan wizualny poprzez ukrywanie rozliczania indeksów i enkapsulację iteracji do innej iteracji ( enumerate obiekt), który daje dwupunktową krotkę indeksu i pozycję, którą zapewniłby pierwotny iterowalny. Wygląda to tak:

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

Ten przykładowy kod jest dość dobrze kanoniczny przykład różnicy między kodem, który jest idiomatyczny w Pythonie, a kodem, który nie jest. Kod idiomatyczny to wyrafinowany (ale nie skomplikowany) język Python, napisany w sposób, w jaki zamierzano go użyć. Kodeks Idiomatic jest oczekiwany przez projektantów języka, co oznacza, że ​​zwykle ten kod jest nie tylko bardziej czytelny, ale także bardziej wydajny.

Zdobywanie liczyć

Nawet jeśli nie potrzebujesz indeksów, ale potrzebujesz liczby iteracji (czasem pożądanych), możesz zacząć od 1 a ostateczna liczba będzie twoim rachunkiem.

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

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

Liczenie wydaje się być bardziej tym, o co masz zamiar poprosić (w przeciwieństwie do indeksu), kiedy powiedziałeś, że chcesz od 1 do 5.


Breaking down - wyjaśnienie krok po kroku

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

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

Teraz przekazujemy tę iterowalną do wyliczenia, tworząc obiekt wyliczeniowy:

enumerate_object = enumerate(items) # the enumerate object

Możemy wyciągnąć pierwszy element z tej iteracji, że otrzymamy pętlę z next funkcjonować:

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

I widzimy, że dostaliśmy krotkę 0, pierwszy indeks, i 'a', pierwszy element:

(0, 'a')

możemy użyć tego, co nazywa się "rozpakowywanie sekwencji"aby wyodrębnić elementy z tej dwu-krotki:

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

i kiedy sprawdzamy index, uważamy, że odnosi się do pierwszego indeksu, 0, i item odnosi się do pierwszego przedmiotu, 'a'.

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

Wniosek

  • Indeksy Pythona zaczynają się od zera
  • Aby uzyskać indeksy z iteracji podczas iteracji, użyj funkcji wyliczania
  • Użycie wyliczenia w idiomatyczny sposób (wraz z rozpakowywaniem krotek) tworzy kod, który jest bardziej czytelny i łatwiejszy w utrzymaniu:

Zrób to:

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

519
2018-01-21 17:11





Zaczyna się to bardzo proste 1 inny niż 0:

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

Uwaga

Ważna wskazówka, choć trochę myląca od tego czasu index Będzie tuple  (idx, item) tutaj. Dobrze iść.


105
2018-05-27 10:04



Pytanie dotyczyło indeksów list; ponieważ zaczynają się od 0, nie ma sensu zaczynać od innej liczby, ponieważ indeksy byłyby błędne (tak, OP również uznał to za niewłaściwe). W przeciwnym razie wywołanie zmiennej, która jest krotką index, item właśnie index jest bardzo mylące, jak zauważyłeś. Po prostu użyj for index, item in enumerate(ints). - Antti Haapala
Lepiej jest załączyć indeks wewnątrz par nawiasów jako (indeks), będzie działać zarówno w wersjach 2, jak i 3 w Pythonie. - hygull


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

67
2018-02-06 22:49



Tak powinno być xrange dla wersji przed 3.0. - Ben Blank
Nie, chyba że potrzebna jest prędkość, nie należy optymalizować. - Georg Schölly
Nie należy przedwcześnie zoptymalizować, chociaż zgadzam się w tym przypadku, ponieważ ten sam kod działa w wersjach 2.x i 3.x.
Zamiast tego użyj wyliczenia - saulspatz
W przypadku Pythona 2.3 powyżej użyj funkcji wbudowanej, ponieważ jest to bardziej Python. - januarvs


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

1. Korzystanie z wyliczenia (uważany za najbardziej idiomatyczny)

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

Jest to również najbezpieczniejsza opcja w mojej opinii, ponieważ szansa wejścia w nieskończoną rekursję została wyeliminowana. Zarówno element, jak i jego indeks przechowywane są w zmiennych i nie ma potrzeby zapisywania żadnego kolejnego kodu aby uzyskać dostęp do przedmiotu.

2. Tworzenie zmiennej do przechowywania indeksu (za pomocą for)

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 (za pomocą while)

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 tutaj wyjaśnione i mogą nawet zastosować więcej w innych sytuacjach. na przykład za pomocą itertools.chain z dla. Obsługuje zagnieżdżone pętle lepiej niż inne przykłady.


34
2017-08-15 02:17



W punkcie 2 dostęp z .index() ma liniową złożoność, co oznacza, że ​​złożoność twojej pętli jest teraz kwadratowa. Co więcej, nie działa, gdy twoja lista zawiera kilka równych elementów, ponieważ zawsze zwraca indeks pierwszego. - Aristide
@Charitoo Usuwam punkt 2, ponieważ tak naprawdę nigdy nie powinien być używany - jamylak
Czy możesz mieć wiele wyliczeń w tym samym czasie? Powiedz, że chcę, aby ja i J były takie wskaźniki, że J> ja itd.? Przypuszczam, że 3 byłoby na to lepsze - arviman


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

20
2018-02-06 22:52



To jest nie źle i jest używany w C / C ++ i innych. Jest uważany za nie-pytoniczny, ale może być również używany w pythonie. Jak proste rozwiązania, które dzielą to na źródło: + - Valor Naram
Gdzie jest napisane, że jest źle? - Charlie Martin
Jakiś pyton ekstremiści Powiedziałbym, nie rób tego. Ale powiedziałem to tylko po to, aby wskazać, że istnieje więcej niż jeden możliwy sposób - Valor Naram


Najszybszy sposób dostępu do indeksów listy w pętli Python 2.7 jest użycie metoda zasięgu dla małych list i wyliczyć metodę dla średnich i dużych list wielkości.

Proszę zobaczyć różne podejścia który może być użyty do iteracji na liście i dostępu do wartości indeksu i ich wskaźniki wydajności (które, jak przypuszczam, byłyby użyteczne dla ciebie) 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 dane o skuteczności dla każdej z poniższych metod:

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 range Metoda jest najszybsza do wystawienia na 1000 pozycji. Dla listy o wielkości> 10 000 pozycji enumerate jest zwycięzcą.

Dodanie przydatnych linków poniżej:


16
2017-08-04 09:49



"czytelność się liczy" Różnica prędkości w małym zakresie <1000 jest nieistotna. Jest o 3% wolniejszy w przypadku już małej metryki czasu. - Surest Texas