Доступ до індексу в циклі "for"?


3602

Як отримати доступ до індексу в forциклі, як описано нижче?

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

Я хочу отримати такий вихід:

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

Коли я проходжу цикл через нього за допомогою forциклу, як я можу отримати доступ до індексу циклу від 1 до 5 в цьому випадку?


42
Зауважте, що індекси в python починаються від 0, тому індекси для вашого списку прикладів становлять 0 до 4, а не 1 до 5
підключення

Відповіді:


6108

Використання додаткової змінної стану, наприклад змінної індексу (яку ви зазвичай використовуєте в таких мовах, як C або PHP), вважається непітонічною.

Кращим варіантом є використання вбудованої функції enumerate(), доступної як в Python 2, так і в 3:

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

Перегляньте PEP 279 для отримання додаткової інформації.


61
Як Аарон вказує нижче, використовуйте start = 1, якщо ви хочете отримати 1-5, а не 0-4.
clozach

2
Чи enumerateне понесе ще один накладний?
TheRealChx101

@ TheRealChx101 згідно з моїми тестами (Python 3.6.3) різниця незначна, а іноді навіть на користь enumerate.
Błotosmętek

804

Як за допомогою циклу for, як отримати доступ до індексу циклу, від 1 до 5 в цьому випадку?

Використовуйте enumerateдля отримання індексу з елементом під час ітерації:

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

І зауважте, що індекси Python починаються з нуля, тож ви отримаєте 0 до 4 із зазначеним вище. Якщо ви хочете рахувати від 1 до 5, зробіть це:

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

Унідіоматичне управління потоком

Що ви просите, це пітонічний еквівалент наступного, що є алгоритмом, який використовує більшість програмістів мов нижчого рівня:

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

Або мовами, які не мають циклу для кожного:

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

або іноді частіше (але унідіоматично) зустрічається в Python:

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

Використовуйте функцію перерахування

enumerateФункція Python зменшує візуальне скупчення, приховуючи облік індексів, і інкапсулює ітерабел в інший ітерабельний ( enumerateоб'єкт), який дає двофакторний кордону індексу та елемент, який надав би оригінальний ітерабел. Це виглядає приблизно так:

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

Цей зразок коду досить добре є канонічним прикладом різниці між кодом, який є ідіоматичним для Python, і кодом, який не є. Ідіоматичний код - це складний (але не складний) Python, написаний у такий спосіб, яким він був призначений для використання. Ідіоматичний код очікується дизайнерами мови, а це означає, що зазвичай цей код є не просто більш читабельним, але й більш ефективним.

Отримання рахунку

Навіть якщо індекси вам не потрібні, але вам потрібна кількість ітерацій (іноді бажаних), з яких ви можете почати, 1і остаточне число буде вашим рахунком.

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

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

Здається, що кількість рахунків є більшою, ніж ви хочете попросити (на відміну від індексу), коли ви сказали, що хочете від 1 до 5.


Розбити його - покрокове пояснення

Щоб розбити ці приклади, скажімо, у нас є список елементів, які ми хочемо повторити за допомогою індексу:

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

Тепер ми передаємо цей ітерабельний для перерахування, створюючи перерахований об'єкт:

enumerate_object = enumerate(items) # the enumerate object

Ми можемо витягнути перший елемент із цього ітерабельного, який ми отримаємо в циклі з nextфункцією:

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

І ми бачимо, що ми отримуємо кортеж 0, перший індекс і 'a', перший пункт:

(0, 'a')

ми можемо використовувати те, що позначається як " розпакування послідовності ", щоб витягти елементи з цього двоякого:

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

і коли ми досліджуємо index, ми знаходимо , що відноситься до першого індексу, 0, і itemвідноситься до першого пункту 'a'.

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

Висновок

  • Індекси Python починаються з нуля
  • Щоб отримати ці індекси з ітерабельного під час повторення, скористайтеся функцією перерахування
  • Використовуючи перерахування в ідіоматичному способі (разом з розпакуванням кортежу) створюється код, який можна прочитати і можна легко зрозуміти:

Тож зробіть це:

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

1
Чи працює приклад " Отримання рахунку ", коли itemsпорожній?
Бергі

Я надсилаю дані за допомогою ajax на представлення Django як масив у вигляді двох значень змінної legData зі значеннями як [1406, 1409]. Якщо я друкую на консоль за допомогою print(legData), вихід буде [1406,1409] . Однак, якщо я спробую проаналізувати окремі значення списку, як-от for idx, xLeg in enumerate(legData): print(idx, xLeg), це отримує мені вихід окремих цілих чисел, таких як [, 1, 4, 0, 6 і так далі проти індексів 0, 1, 2, 3, 4 тощо (так, квадратні дужки та кома також виводяться так, ніби вони були частиною самих даних ). Що тут не так?
користувач12379095

@ user12379095 у вас, ймовірно, є дані неправильного типу (рядок), і вам потрібно перетворити їх у фактичний список чисел замість рядка. Це дещо поза темою, будь ласка, видаліть ваш коментар і прапор мій буде видалений, як це більше не потрібно, коли ви бачите це.
Зал Аарона

152

Почати це досить просто, 1ніж 0:

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

Примітка

Важливий натяк, хоч і трохи оманливий, оскільки indexбуде tuple (idx, item)тут. Можеш йти.


11
Питання стосувалося індексів списку; оскільки вони починаються з 0, то мало починати починати з іншого числа, оскільки індекси були б помилковими (так, ОП заявила, що це також неправильно у питанні). Інакше називати змінну, яка є index, itemпростою index, дуже вводить в оману, як ви зазначили. Просто використовуйте for index, item in enumerate(ints).
Антті Хаапала

1
Краще, щоб індекс всередині парних дужок було зафіксовано як (індекс), він працюватиме як на версіях Python 2, так і на 3.
hygull

1
@AnttiHaapala Причина, я припускаю, полягає в тому, що очікуваний результат питання починається з індексу 1, а не 0
пушкін

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

10
Це, мабуть, має бути xrangeдля попереднього 3.0.
Бен Бланк

43
Використовуйте замість перерахування
saulspatz

3
Для Python 2.3 вище, використовуйте вбудовану функцію, оскільки вона є більш Pythonic.
січняв

Перерахувати не завжди краще - це залежить від вимог заявки. У моїй теперішній ситуації зв'язки між довжинами об'єкта мають значення для мого застосування. Хоча я почав використовувати перерахування, я перейшов на такий підхід, щоб уникнути необхідності писати логіку, щоб вибрати, який об’єкт перелічити.
ad

1
@adg Я не бачу, як уникнути enumerateзбереження будь-якої логіки; вам все одно потрібно вибрати, з яким об’єктом індексувати i, ні?
чепнер

47

Як і норма в Python, існує кілька способів зробити це. У всіх прикладах припускають:lst = [1, 2, 3, 4, 5]

1. Використання перерахування ( вважається найбільш ідіоматичним )

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

На мій погляд, це також найбезпечніший варіант, оскільки шанс потрапити в нескінченну рекурсію був виключений. І елемент, і його індекс утримуються змінними, і немає необхідності писати будь-який додатковий код для доступу до елемента.

2. Створення змінної для утримування індексу ( використанняfor )

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

3. Створення змінної для утримування індексу ( використанняwhile )

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

4. Завжди є інший спосіб

Як було пояснено раніше, існують інші способи зробити це, які тут не пояснені, і вони можуть навіть застосувати більше в інших ситуаціях. наприклад, використання itertools.chainдля. Він обробляє вкладені петлі краще, ніж інші приклади.


30

Старомодний спосіб:

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

Розуміння списку:

[ (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
Це НЕ так , і використовується в C / C ++ та інші. Він вважається непітонічним, але може бути використаний і в пітоні. Як і прості рішення, які розбивають його на джерело: +
Valor Naram

Деякі екстремісти пітона сказали б, не робіть цього. Але я сказав це лише для того, щоб вказати, що існує більше одного можливого способу
доблесть Нарама

21

Найшвидший спосіб отримати доступ до індексів списку в циклі в Python 2.7 - це використовувати метод діапазону для невеликих списків та метод перерахування для списків середнього та величезного розміру.

Будь ласка, ознайомтеся з різними підходами, які можна використовувати для перебору значень списку та доступу до індексу доступу та показників їх продуктивності (які, мабуть, були б корисні для вас) у зразках коду нижче:

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

Перегляньте показники ефективності для кожного методу нижче:

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

В результаті використання rangeметоду є найшвидшим до списку з 1000 предметами. Для списку розміром> 10 000 предметів enumerate- переможець.

Додавання корисних посилань нижче:


5
"кількість читабельності" Різниця швидкостей у малому діапазоні <1000 незначна. Це на 3% повільніше і без того невеликий показник часу.

Як щодо оновлення відповіді на Python 3?
Георгій

14

Перш за все, індекси будуть від 0 до 4. Мови програмування починають рахувати з 0; не забувайте про це, інакше ви натрапите на індекс поза межами меж. Все, що вам потрібно в циклі for, - це змінна кількість, що рахує від 0 до 4 так:

for x in range(0, 5):

Майте на увазі, що я написав 0 - 5, тому що цикл зупиняє одне число перед макс. :)

Щоб отримати значення індексу, використовуйте

list[index]

13

Ось що ви отримуєте, коли ви отримуєте доступ до індексу в forциклі:

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

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

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

Результат:

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

Результат:

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

Результат:

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

12

Відповідно до цього обговорення: http://bytes.com/topic/python/answers/464012-objects-list-index

Ітерація лічильника циклу

Поточна ідіома для циклічного перегляду індексів використовує вбудовану rangeфункцію:

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

Циркулювання над елементами та індексами може бути досягнуто або старою ідіомою, або за допомогою нової zipвбудованої функції:

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

або

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

через http://www.python.org/dev/peps/pep-0212/


22
Це не працюватиме для ітерації через генератори. Просто використовуйте enumerate ().
Тадек

В даний час поточна ідіома перелічена, а не виклик діапазону.
TankorSmash

і це те саме, що і старша відповідь: stackoverflow.com/a/522576/6451573
Жан-Франсуа Фабре

11

Ви можете зробити це за допомогою цього коду:

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

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

Використовуйте цей код, якщо вам потрібно скинути значення індексу в кінці циклу:

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

Найкращим рішенням цієї проблеми є використання функції перерахування вбудованого пітона.
перерахувати повернутий кортеж
перше значення - індекс,
друге значення - елемент масиву в цьому індексі

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

У своєму запитанні ви пишете "як мені отримати доступ до індексу циклу, від 1 до 5 в цьому випадку?"

Однак індекс для списку працює з нуля. Отже, тоді ми повинні знати, чи дійсно ви хочете - це індекс і пункт для кожного елемента в списку, чи ви дійсно хочете числа, починаючи з 1. На щастя, в Python легко зробити і те, і інше.

По-перше, для уточнення, enumerateфункція ітеративно повертає індекс і відповідний елемент для кожного елемента в списку.

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

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

Вихід для вищезазначеного є,

0 1
1 2
2 3
3 4
4 5

Зауважте, що індекс працює від 0. Цей тип індексації поширений серед сучасних мов програмування, включаючи Python та C.

Якщо ви хочете, щоб ваш цикл охоплював частину списку, ви можете використовувати стандартний синтаксис Python для частини списку. Наприклад, для циклу від другого елемента в списку до, але не включаючи останнього, ви можете використовувати

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

Зауважте, що ще раз індекс виходу працює від 0,

0 2
1 3
2 4

Це приводить нас до start=nперемикача для enumerate(). Це просто компенсує індекс, ви можете еквівалентно просто додати число до індексу всередині циклу.

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

для якого є вихід

1 1
2 2
3 3
4 4
5 5

9

Якби я перейшов, nums = [1, 2, 3, 4, 5]я би зробив

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

Або отримати довжину як l = len(nums)

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

7

Якщо у списку немає повторюваного значення:

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

1
Зауважте, що перший варіант не слід використовувати, оскільки він працює правильно лише тоді, коли кожен елемент у послідовності є унікальним.
Стам Кали

2
Перший варіант - O (n²), жахлива ідея. Якщо ваш список має 1000 елементів, це займе буквально в 1000 разів довше, ніж використання enumerate. Ви повинні видалити цю відповідь.
Борис

5

Ви також можете спробувати це:

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)

Вихід є

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

3

Можна використовувати indexметод

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

EDIT У коментарі підкреслено, що цей метод не працює, якщо в ньому є дублікати ints, метод нижче повинен працювати для будь-яких значень у ints:

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

Або в якості альтернативи

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

якщо ви хочете отримати як індекс, так і значення у intsвигляді списку кортежів.

Він використовує метод enumerateобраної відповіді на це питання, але з розумінням списку, що робить його швидшим із меншим кодом.


2

Простий відповідь за допомогою циклу while:

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

Вихід:

введіть тут опис зображення


1

Щоб надрукувати кортеж (індекс, значення) в розумінні списку за допомогою forциклу:

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

Вихід:

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

1

Це достатньо добре відповідає цілі:

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

4
Це зруйнується, якщо в списку index()будуть повторювані елементи, як і пошук першого появи x, не згадуючи часу O ( n ^ 2 ), необхідного для пошуку кожного елемента.
Петро Шолдан

повністю погодився, що він не працюватиме для дублікатів елементів у списку Після цього я також вивчаю пітон.
Суміт Кумар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.