'For' döngülerindeki dizine erişiliyor mu?


3605

forDizine aşağıdaki gibi bir döngüde nasıl erişebilirim ?

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

Bu çıktıyı almak istiyorum:

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

Bir döngü kullanarak fordöngü yaptığımda, bu durumda döngü dizinine 1'den 5'e nasıl erişebilirim?


Yanıtlar:


6116

İndeks değişkeni (normalde C veya PHP gibi dillerde kullanacağınız) gibi ek bir durum değişkeninin kullanılması pitonik olmayan olarak kabul edilir.

Daha iyi seçenek, enumerate()hem Python 2 hem de 3'te bulunan yerleşik işlevi kullanmaktır :

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

Daha fazla bilgi için PEP 279'a göz atın .


61
Aaron aşağıda belirtildiği gibi, 0-4 yerine 1-5 almak istiyorsanız start = 1 kullanın.
clozach

2
enumerateBaşka bir ek yüke neden olmaz mı ?
TheRealChx101

@ TheRealChx101 testlerime göre (Python 3.6.3) fark göz ardı edilebilir ve hatta bazen lehine enumerate.
Błotosmętek

804

For döngüsü kullanarak, bu durumda 1'den 5'e kadar döngü dizinine nasıl erişebilirim?

enumerateYinelediğiniz öğeyi içeren dizini almak için kullanın :

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

Ve Python'un dizinlerinin sıfırdan başladığını unutmayın, böylece yukarıdakilerle 0 ila 4 elde edersiniz. 1'den 5'e kadar sayımı istiyorsanız, bunu yapın:

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

Unidiomatik kontrol akışı

İstediğiniz şey, düşük seviyeli dillerin çoğunun programcılarının kullanacağı algoritma olan aşağıdakilerin Pythonic eşdeğeridir:

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

Veya for-each döngüsü olmayan dillerde:

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

veya bazen Python'da daha yaygın olarak bulunur (ancak tek yönlü olarak):

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

Numaralandırma İşlevini Kullanma

Python'un enumerateişlevi , indekslerin muhasebesini gizleyerek ve yinelenebilir olanı, enumerateiki maddelik bir indeks ve tekrarlanabilir orijinalin sağlayacağı öğeyi veren başka bir yinelenebilir ( nesne) içine alarak görsel karmaşayı azaltır . Şöyle görünüyor:

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

Bu kod örneği, Python'un deyimiyle kod ile olmayan kod arasındaki farkın kanonik örneğidir. Deyimsel kod, kullanılması amaçlandığı şekilde yazılan sofistike (ancak karmaşık olmayan) Python'dur. Deyimsel kod, dilin tasarımcıları tarafından beklenir, bu da genellikle bu kodun sadece daha okunabilir değil, aynı zamanda daha verimli olduğu anlamına gelir.

Sayma

Gittikçe indekslere ihtiyacınız olmasa bile, başlayabileceğiniz bir 1dizi iterasyona (bazen istenir) ihtiyacınız vardır ve son sayı sizin sayınız olacaktır.

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

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

Sayı 1'den 5'e istediğinizi söylediğinizde (endeksin aksine) istemek istediğiniz şey gibi görünüyor.


Parçalamak - adım adım açıklama

Bu örnekleri parçalamak için, bir dizinle tekrarlamak istediğimiz öğelerin bir listesine sahip olduğumuzu varsayalım:

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

Şimdi bu numaralandırılabilir bir sayım nesnesi yaratarak sayılabilir:

enumerate_object = enumerate(items) # the enumerate object

İlk öğeyi, nextfonksiyonla bir döngü halinde alacağımız bu tekrarlanabilir durumdan çıkarabiliriz :

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

Ve görüyorum ki 0, ilk endekse ve 'a'ilk maddeye ait bir grup elde ediyoruz :

(0, 'a')

bu iki demetten elemanları çıkarmak için " dizi açma " olarak adlandırılabilir :

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

ve incelediğimizde index, ilk endekse, 0 ve itemilk maddeye atıfta bulunuruz 'a'.

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

Sonuç

  • Python dizinleri sıfırdan başlar
  • Bu dizinleri, yinelediğinizde yinelemeden almak için numaralandırma işlevini kullanın
  • Numaralandırmayı deyimsel olarak kullanmak (demet açma ile birlikte) daha okunabilir ve bakımı kolay bir kod oluşturur:

Öyleyse bunu yapın:

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

1
" Sayım elde etme " örneği itemsboşken çalışır mı?
Bergi

Bir değişken olarak, iki değerleri biçiminde bir dizi olarak Django görünümlere ajax kullanarak veri gönderme am legData olarak değerlerle [1406, 1409]. Kullanarak konsola yazdırırsam print(legData)çıktı [1406,1409] olur . Ancak, listenin tek tek değerlerini aşağıdaki gibi ayrıştırmaya çalışırsam, 0, 1, 2, 3, 4for idx, xLeg in enumerate(legData): print(idx, xLeg) indekslerine karşı [, 1, 4, 0, 6 vb. Gibi tek tek tamsayıların çıktısını alır. vb. (evet, köşeli parantezler ve virgüller de verilerin bir parçasıymış gibi çıkarılmaktadır ). Burada yanlış giden ne?
user12379095

@ user12379095 büyük olasılıkla yanlış türde (bir dize) veriye sahipsiniz ve bir dize yerine gerçek bir sayı listesine dönüştürmeniz gerekiyor. Bu biraz konu dışı, lütfen yorumunuzu silin ve bunu gördüğünüzde artık silinmeyecek şekilde işaretleyin.
Aaron Hall

152

Şunlardan 1başka bir yöntemle başlatmak oldukça basittir 0:

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

Not

Önemli ipucu, biraz yanıltıcı olsa indexda tuple (idx, item)burada olacak . Gitmek güzel.


11
Soru liste indeksleri ile ilgiliydi; 0'dan başladıkları için, indekslerin yanlış olacağı için diğer sayıdan başlamanın çok az anlamı vardır (evet, OP de soruda yanlış dedi). Aksi takdirde, belirttiğiniz gibi , index, itemsadece bir demet olan değişkeni çağırmak indexçok yanıltıcıdır. Sadece kullan for index, item in enumerate(ints).
Antti Haapala

1
Daha
iyisi

1
@AnttiHaapala nedeni, sanırım, soru indeksi 1 yerine 0 çıkış başlar beklenen olmasıdır
Puşkin

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

10
Muhtemelen xrange3.0 öncesi için olmalı .
Ben Blank

43
Bunun yerine numaralandırma kullanın
saulspatz

3
Yukarıdaki Python 2.3 için, daha Pythonic olduğu için numaralandırma yerleşik işlevini kullanın.
Ocak

Numaralandırma her zaman daha iyi değildir - uygulamanın gereksinimlerine bağlıdır. Mevcut durumumda, nesne uzunlukları arasındaki ilişkiler uygulamam için anlamlıdır. Numaralandırma kullanmaya başlasam da, numaralandırılacak nesneyi seçmek için mantık yazmak zorunda kalmamak için bu yaklaşıma geçtim.
adg

1
@adg enumerateHerhangi bir mantığın nasıl saklanacağını göremiyorum ; hala endekslenecek nesneyi seçmeniz gerekiyor i, değil mi?
chepner

47

Python'daki norm olduğu gibi, bunu yapmanın birkaç yolu vardır. Tüm örneklerde varsayalım:lst = [1, 2, 3, 4, 5]

1. Numaralandırma kullanma ( en deyimsel olarak kabul edilir )

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

Bu da bence en güvenli seçenektir çünkü sonsuz tekrarlamaya girme şansı ortadan kaldırılmıştır. Hem öğe hem de dizini değişkenlerde tutulur ve öğeye erişmek için başka kod yazmanıza gerek yoktur.

2. Dizini tutmak için bir değişken oluşturma ( kullanarakfor )

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

3. Dizini tutmak için bir değişken oluşturma ( kullanarakwhile )

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

4. Her zaman başka bir yol vardır

Daha önce açıklandığı gibi, burada açıklanmayan başka yollar da vardır ve bunlar başka durumlarda daha fazla uygulanabilir. örneğin kullanarak itertools.chainiçin birlikte. İç içe ilmekleri diğer örneklerden daha iyi işler.


30

Eski moda yol:

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

Liste anlama:

[ (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
Bu yanlış değildir ve C / C ++ ve diğerlerinde kullanılır. Pitonik olmayan olarak kabul edilir, ancak python'da da kullanılabilir. Kaynağa
ayıran

Bazı python aşırılık yanlıları derler, bunu yapma. Ama sadece birden fazla olası yol olduğunu göstermek için söyledim
Valor Naram

21

Python 2.7'de döngü içindeki liste dizinlerine erişmenin en hızlı yolu, küçük listeler için aralık yöntemini kullanmak ve orta ve büyük boyutlu listeler için numaralandırma yöntemini kullanmaktır.

Lütfen aşağıdaki kod örneklerinde liste ve erişim endeksi değeri ve bunların (sizin için yararlı olacağını varsayalım) performans metriklerini yinelemek için kullanılabilecek farklı yaklaşımlara bakın:

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

Aşağıdaki her yöntem için performans metriklerine bakın:

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

Sonuç olarak, rangeyöntemi kullanmak 1000 öğe ile listenin en hızlısıdır. 10.000'den büyük ürün listesi enumerateiçin kazanan.

Aşağıya bazı yararlı bağlantılar ekleme:


5
"okunabilirlik önemlidir" Küçük <1000 aralığındaki hız farkı önemsizdir. Zaten küçük bir zaman metriğinde% 3 daha yavaştır.

Python 3'ün cevabını güncellemeye ne dersiniz?
Georgy

14

Her şeyden önce, indeksler 0 ila 4 arasında olacaktır. Programlama dilleri 0'dan saymaya başlar; unutmayın veya sınırlar istisnası dışında bir dizine rastlar. For döngüsünde ihtiyacınız olan tek şey 0'dan 4'e kadar değişen bir değişkendir:

for x in range(0, 5):

Döngü maksimumdan bir sayı önce durduğundan 0 ile 5 yazdığımı unutmayın. :)

Bir dizinin değerini almak için

list[index]

13

forDöngüler halinde dizine erişirken elde edeceğiniz avantajlar şunlardır:

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

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

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

Sonuç:

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

Sonuç:

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

Sonuç:

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

12

Bu tartışmaya göre: http://bytes.com/topic/python/answers/464012-objects-list-index

Döngü sayacı yinelemesi

Endeksler üzerinde döngü için mevcut deyim yerleşik rangeişlevi kullanır:

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

Hem elemanlar hem de indeksler üzerinde döngü yapmak, eski deyim veya yeni zipyerleşik fonksiyon kullanılarak elde edilebilir:

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

veya

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

http://www.python.org/dev/peps/pep-0212/ aracılığıyla


22
Bu, jeneratörler aracılığıyla yineleme için işe yaramaz. Sadece enumerate () kullanın.
Tadeck

Günümüzde, geçerli deyim aralık aralığı değil, numaralandırılmıştır.
TankorSmash


11

Bunu şu kodla yapabilirsiniz:

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

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

Döngünün sonunda dizin değerini sıfırlamanız gerekirse bu kodu kullanın:

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

Bu sorun için en iyi çözüm, numaralandırma yerleşik python işlevini kullanmaktır.
enumerate return tuple
birinci değeri endeks
ikinci değeri o dizindeki dizi elemanıdır

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

Sorunuzda, "bu durumda 1'den 5'e kadar döngü dizinine nasıl erişirim?"

Ancak, bir liste için dizin sıfırdan çalışır. Bu nedenle, aslında bir listede her öğe için dizin ve öğe olup olmadığını veya 1'den başlayan sayıları gerçekten isteyip istemediğinizi bilmeliyiz.

İlk olarak, açıklığa kavuşturmak için enumerateişlev, bir listedeki her öğe için dizini ve karşılık gelen öğeyi yinelemeli olarak döndürür.

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

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

Yukarıdakiler için çıktı o zaman,

0 1
1 2
2 3
3 4
4 5

Dizinin 0'dan çalıştığına dikkat edin. Bu tür dizine ekleme, Python ve C dahil olmak üzere modern programlama dilleri arasında yaygındır.

Döngünüzün listenin bir bölümüne yayılmasını istiyorsanız, listenin bir bölümü için standart Python sözdizimini kullanabilirsiniz. Örneğin, listedeki ikinci öğeden son öğeye kadar olan ancak son öğeyi içermeyen döngüler için

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

Bir kez daha çıktı dizininin 0'dan,

0 2
1 3
2 4

Bu bizi start=nanahtara getirir enumerate(). Bu sadece dizini öteler, döngü içindeki dizine eşdeğer bir sayı ekleyebilirsiniz.

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

bunun için çıktı

1 1
2 2
3 3
4 4
5 5

9

Eğer yineleseydim nums = [1, 2, 3, 4, 5]yapardım

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

Veya uzunluğu l = len(nums)

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

7

Listede yinelenen bir değer yoksa:

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

1
Yalnızca seçenek dizisindeki her öğe benzersiz olduğunda doğru çalıştığından, ilk seçeneğin kullanılmaması gerektiğini unutmayın.
Stam Kaly

2
İlk seçenek O (n²), korkunç bir fikir. Listeniz 1000 öğe uzunluğundaysa, kelimenin tam anlamıyla kullanmaktan 1000 kat daha uzun sürer enumerate. Bu yanıtı silmelisiniz.
Boris

5

Bunu da deneyebilirsiniz:

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)

Çıktı

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

3

indexYöntemi kullanabilirsiniz

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

EDIT Yorumda, yinelenmeler varsa bu yöntemin çalışmadığı vurgulanırsa, intsaşağıdaki yöntemin aşağıdaki değerler için çalışması gerekir ints:

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

Veya alternatif olarak

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

hem indeksi hem de değeri intstuples listesi olarak almak istiyorsanız .

Bu enumeratesoruya seçilen cevapta yöntemi kullanır , ancak liste kavrama ile daha az kodla daha hızlı hale getirir.


2

While Loop kullanarak basit cevap:

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

Çıktı:

resim açıklamasını buraya girin


1

Bir fordöngü kullanarak liste kavramada (dizin, değer) demetini yazdırmak için :

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

Çıktı:

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

1

Bu amaca yeterince iyi hizmet eder:

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

4
Listede, her bir öğeyi aramak için gereken O ( n ^ 2 ) süresinden bahsetmeden, index()ilk oluşumunu arayacak şekilde tekrarlanan öğeler varsa, bu parçalanır . x
Peter Szoldan

tamamen listedeki yinelenen öğeler için çalışmayacağını kabul etti. afterall Ben de python öğreniyorum.
Sumit Kumar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.