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

3608

Как мне получить доступ к индексу в 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
plugwash

Ответы:

6125

Использование дополнительной переменной состояния, такой как индексная переменная (которую вы обычно используете в таких языках, как 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
806

Используя цикл 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)

Unidiomatic контроль потока

То, что вы просите, - это Pythonic-эквивалент следующего: алгоритм, который будет использовать большинство программистов на языках нижнего уровня:

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

Или в языках, где нет цикла for-each:

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 и т. д. (да, квадратные скобки и запятая также выводятся, как если бы они были частью самих данных ). Что здесь не так?
user12379095
@ user12379095 у вас, вероятно, есть данные неверного типа (строка), и вам нужно преобразовать их в фактический список чисел вместо строки. Это несколько не по теме, пожалуйста, удалите свой комментарий и пометьте мой, чтобы он был больше не нужен, когда вы видите это.
Аарон Холл
153

Это довольно просто, чтобы начать с 1другого, чем 0:

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

Запись

Важный намек, хотя и немного вводящий в заблуждение, т.к. indexбудет tuple (idx, item)здесь. Хорошо пойти.

AJ
источник
11
Вопрос был о списочных индексах; поскольку они начинаются с 0, нет смысла начинать с другого числа, так как индексы были бы неправильными (да, ФП также сказал, что это неправильно в вопросе). В противном случае, как вы заметили , вызов переменной, являющейся кортежем index, itemjust, indexвводит в заблуждение. Просто используйте for index, item in enumerate(ints).
Антти Хаапала
1
Лучше заключить индекс в пары скобок как (index), он будет работать как в версиях Python 2, так и в 3.
Hygull
1
@AnttiHaapala Причина, как я полагаю, в том, что ожидаемый результат вопроса начинается с индекса 1, а не с 0
pushkin
90
for i in range(len(ints)):
   print i, ints[i]
Дэвид Ханак
источник
10
Это должно быть, вероятно, xrangeдля pre-3.0.
Бен Бланк
44
Вместо этого используйте перечисление
saulspatz
3
Для Python 2.3 и выше используйте встроенную функцию перечисления, так как она более Pythonic.
Januarvs
Перечислять не всегда лучше - это зависит от требований приложения. В моей текущей ситуации отношения между длинами объектов имеют значение для моего приложения. Хотя я начал использовать перечисление, я переключился на этот подход, чтобы избежать необходимости писать логику для выбора объекта для перечисления.
ADG
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с для. Он обрабатывает вложенные циклы лучше, чем другие примеры.

Charitoo
источник
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 ++ и других. Он считается непитоническим, но также может использоваться в питоне. Как простые решения, которые разбивают его на источник: +
Доблесть Нарам
Некоторые питонские экстремисты скажут: не делайте этого. Но я сказал это только для того, чтобы показать, что существует более одного возможного пути
Доблесть Нарам
21

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

Пожалуйста, ознакомьтесь с различными подходами, которые можно использовать для перебора списка и значения индекса доступа и их метрик производительности (которые, я полагаю, будут полезны для вас) в примерах кода ниже:

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]
ytpillai
источник
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/

thinker007
источник
22
Это не будет работать для перебора генераторов. Просто используйте enumerate ().
Tadeck
В настоящее время текущая идиома - это перечисление, а не вызов диапазона.
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
Liam
источник
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
DrM
источник
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)
RIshu
источник
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]

РЕДАКТИРОВАТЬ Подчеркнуто в комментарии, что этот метод не работает, если есть дубликаты 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в выбранном ответе на этот вопрос, но с пониманием списка, что делает его быстрее с меньшим количеством кода.

PyRsquared
источник
2

Простой ответ с помощью цикла Loop:

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 ), необходимое для поиска каждого элемента.
Питер Шолдан
полностью согласен, что это не будет работать для дубликатов элементов в списке. В конце концов, я также изучаю Python.
Сумит Кумар