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

Как получить доступ к самому индексу для списка, подобного следующему?

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

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

34 ответа

Решение

Использование дополнительной переменной состояния, такой как индексная переменная (которую вы обычно используете в таких языках, как C или PHP), считается непифоническим.

Лучше всего использовать встроенную функцию enumerate() доступно в Python 2 и 3:

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

Проверьте PEP 279 для получения дополнительной информации.

Используя цикл 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 Функция уменьшает визуальный беспорядок, скрывая учет индексов и инкапсулируя итерируемое в другое итерируемое (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 Кроме как 0:

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

Заметка

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

Вот что вы получаете, когда получаете доступ к индексу в for петли:

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

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

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

Надеюсь это поможет.

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

Как правило, в 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 с для. Он обрабатывает вложенные циклы лучше, чем другие примеры.

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

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

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

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

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 это победитель.

Добавив несколько полезных ссылок ниже:

Вы можете использовать enumerateи вставляйте выражения в строковые литералы, чтобы получить решение.

Это простой способ:

      a=[4,5,6,8]
for b, val in enumerate(a):
    print('item #{} = {}'.format(b+1, val))

Прежде всего, индексы будут от 0 до 4. Языки программирования начинают считать с 0; не забывайте об этом, иначе вы встретите исключение индекса за пределами границ. Все, что вам нужно в цикле for, это переменная, считающая от 0 до 4, примерно так:

for x in range(0, 5):

Имейте в виду, что я написал от 0 до 5, потому что цикл останавливается на один номер до макс.:)

Чтобы получить значение индекса используйте

list[index]

Вы можете сделать это с помощью этого кода:

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

Согласно этой дискуссии: http://bytes.com/topic/python/answers/464012-objects-list-index

Итерация счетчика циклов

Текущая идиома для зацикливания индексов использует встроенную функцию range:

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

Циклы по элементам и индексам могут быть достигнуты либо с помощью старой идиомы, либо с помощью новой встроенной функции zip [2]:

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/

В вашем вопросе вы пишете "как мне получить доступ к индексу цикла, от 1 до 5 в этом случае?"

Однако индекс для списка запускается с нуля. Итак, нам нужно знать, действительно ли вам нужен индекс и элемент для каждого элемента в списке, или вы действительно хотите, чтобы числа начинались с 1. К счастью, в python это легко сделать и тем, и другим.

Во-первых, чтобы уточнить, функция перечисления итеративно возвращает индекс и соответствующий элемент для каждого элемента в списке.

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

Если бы я перебрал числа = [1,2,3,4,5], я бы сделал

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

Или получите длину как l = len(числа)

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

Я не знаю, является ли следующее pythonic или нет, но он использует функцию Python enumerate и печатает индекс и значение.

int_list = [8, 23, 45, 12, 78]
for index, value in enumerate(int_list):
   print(index, value)

Выход:

0 8
1 23
2 45
3 12
4 78
ints = [9, 23, 45, 12, 78]
ints.extend([1,2,3,4,5,6,7,8])
for idx, val in enumerate(ints):
    print(idx,val)

Таким образом, вы можете расширить список. Расширить означает, что вы можете добавить несколько значений одновременно.

Чтобы добавить этот список, вы должны написать код, указанный ниже:

ints = [9, 23, 45, 12, 78]
ints.append([1])
for idx, val in enumerate(ints):
    print(idx,val)

Таким образом, вы можете добавить одно значение за раз. Если ты пишешь ints.append([1]) так что это создаст подсписок для этого элемента.

Если в списке нет повторяющихся значений:

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

В противном случае используйте enumerate,

for counter, value in enumerate(ints):
    print(counter, value)

ИЛИ использовать ниже:

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

Вы также можете попробовать это:

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

Лучшее решение этой проблемы - использовать встроенную функцию Python.
перечислить возвращаемый кортеж
первое значение индекса
Второе значение является элементом массива по этому индексу

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)

Вы можете использовать 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 в выбранном ответе на этот вопрос, но с пониманием списка, что делает его быстрее с меньшим количеством кода.

Простой ответ с использованием цикла while:

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

Выход:

Вы можете просто использовать переменную count для подсчета количества элементов в списке

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

Чтобы напечатать кортеж (индекс, значение) в понимании списка, используя 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)]

Еще один способ запустить счетчик в цикле for — использоватьitertools.count.

      from itertools import count

my_list = ['a', 'b', 'a']
for i, item in zip(count(), my_list):
    print(i, item)

Это особенно полезно, если вы хотите, чтобы счетчики были дробными числами. В следующем примере «индекс» начинается с 1,0 и увеличивается на 0,5 на каждой итерации.

      my_list = ['a', 'b', 'a']

for i, item in zip(count(start=1., step=0.5), my_list):
    print(f"loc={i}, item={item}")
    
# loc=1.0, item=a
# loc=1.5, item=b
# loc=2.0, item=a

Другой метод — использовать внутри цикла. Однако, в отличие от других ответов на этой странице, в которых упоминается этот метод ( 1, 2, 3), методу необходимо передать начальную точку поиска по индексу (которая является вторым аргументом). Это позволяет добиться двух целей: (1) не требует повторного повторного перебора списка с самого начала; (2) Можно найти индекс всех значений, даже дубликатов.

      my_list = ['a', 'b', 'a']
idx = -1
for item in my_list:
    idx = my_list.index(item, idx+1)
    #                         ^^^^^   <---- start the search from the next index
    print(f"index={idx}, item={item}")
    
# index=0, item=a
# index=1, item=b
# index=2, item=a

С точки зрения производительности, если вам нужны все/большинство индексов, это самый быстрый вариант. Если вы искали только конкретные индексы, это может быть более эффективно. Ниже приведены два примера, где это более эффективно.

Пример №1: Индекс конкретных значений

Предположим, вы хотите найти все индексы, в которых в списке появляется определенное значение (например, наибольшее значение). Например, в следующем случае мы хотим найти все индексы, в которых встречается 2. Это однострочный вызов с использованием . Однако мы также можем искать индексы 2, используя метод в цикле while; как упоминалось ранее, на каждой итерации мы начинаем поиск по индексу с того места, на котором остановились на предыдущей итерации.

      lst = [0, 2, 1, 2]
target = 2

result = []
pos = -1
while True:
    try:
        pos = lst.index(target, pos+1)
        result.append(pos)
    except ValueError:
        break
        
print(result)      # [1, 3]

Фактически, в некоторых случаях это намного быстрее, чем опция, которая выдает тот же результат, особенно если список длинный.

Пример №2: Индекс первого числа, меньшего целевого.

Другое распространенное упражнение, в котором индекс часто необходим в цикле, — это поиск индекса первого элемента в списке, который удовлетворяет некоторому условию (например, больше/меньше некоторого целевого значения). В следующем примере мы хотим найти индекс первого значения, превышающего 2,5. Это однострочное использование, но использование более эффективно, поскольку получение индексов, которые не будут использоваться, как вenumerate()имеет стоимость (котораяlist.index()не повлечет за собой).

      my_list = [1, 2, 3, 4]
target = 2.5

for item in my_list:
    if item > target:
        idx = my_list.index(item)
        break

или в виде однострочника:

      idx = next(my_list.index(item) for item in my_list if item > target)


Код, используемый для построения графика соотношения скоростей во время выполнения:

      import random
import matplotlib.pyplot as plt
import perfplot


def enumerate_1(lst, target=3):
    return [i for i, v in enumerate(lst) if v == target]


def list_index_1(lst, target=3):
    result = []
    pos = -1
    while True:
        try:
            pos = lst.index(target, pos+1)
            result.append(pos)
        except ValueError:
            break
    return result


def list_index_2(lst, target):
    for item in lst:
        if item > target:
            return lst.index(item)


def enumerate_2(lst, target):
    return next(i for i, item in enumerate(lst) if item > target)


setups = [lambda n: [random.randint(1, 10) for _ in range(n)], 
          lambda n: (list(range(n)), n-1.5)]
kernels_list = [[enumerate_1, list_index_1], [enumerate_2, list_index_2]]
titles = ['Get indices of a value', 'Get index that satisfies a condition']
n_range = [2**k for k in range(1,21)]
labels = ['enumerate', 'list.index']
xlabel = 'list length'

fig, axs = plt.subplots(1, 2, figsize=(10, 5), facecolor='white', dpi=60)
for i, (ax, su, ks, t) in enumerate(zip(axs, setups, kernels_list, titles)):
    plt.sca(ax)
    perfplot.plot(ks, n_range, su, None, labels, xlabel, t, relative_to=1)
    ax.xaxis.set_tick_params(labelsize=13)
plt.setp(axs, ylim=(0.7, 2.4), yticks=[i*0.25 + 0.75 for i in range(7)], 
         xlim=(1, 1100000), xscale='log', xticks=[1, 100, 10000, 1000000])
fig.tight_layout();

В дополнение ко всем превосходным ответам выше, вот решение этой проблемы при работе с объектами серии pandas. Во многих случаях серии pandas имеют настраиваемые/уникальные индексы (например, уникальные строки идентификаторов), к которым нельзя получить доступ с помощью функции.

       xs = pd.Series([8, 23, 45])

xs.index = ['G923002', 'G923004', 'G923005']

print(xs)

Выход:

       #    G923002     8
#    G923004    23
#    G923005    45
#    dtype: int64

Мы можем видеть ниже, чтоenumerate()не дает нам желаемого результата:

       for id, x in enumerate(xs):
    print("id #{} = {}".format(id, x))

Выход:

       #    id #0 = 8
#    id #1 = 23
#    id #2 = 45

Мы можем получить доступ к индексам серии pandas в цикле for, используя.items():

       for id, x in xs.items():
    print("id #{} = {}".format(id, x))

Выход:

       #    id #G923002 = 8
#    id #G923004 = 23
#    id #G923005 = 45

Любители однострочных:

      [index for index, datum in enumerate(data) if 'a' in datum]

Объяснение:

      >>> data = ['a','ab','bb','ba','alskdhkjl','hkjferht','lal']
>>> data
['a', 'ab', 'bb', 'ba', 'alskdhkjl', 'hkjferht', 'lal']
>>> [index for index, datum in enumerate(data) if 'a' in datum]
[0, 1, 3, 4, 6]
>>> [index for index, datum in enumerate(data) if 'b' in datum]
[1, 2, 3]
>>>

Очки, которые нужно взять:

  • Python не предоставляет индекс; если вы используетеfor
  • Если выenumerateэто вернет вам ДРУГОЙlist
    • НО этот список будет иметь другой тип
    • он будет обертывать каждый элемент индексом какtuple
    • мы можем обращаться к кортежам как к переменным, разделенным запятой(,)

Спасибо. Сохрани меня в своих молитвах.

Вы можете использоватьrange(len(some_list))а затем найдите индекс, подобный этому

      xs = [8, 23, 45]
for i in range(len(xs)):
    print("item #{} = {}".format(i + 1, xs[i]))

Или используйте встроенный в Pythonenumerateфункция, которая позволяет вам перебирать список и получать индекс и значение каждого элемента в списке

      xs = [8, 23, 45]
for idx, val in enumerate(xs, start=1):
    print("item #{} = {}".format(idx, val))

Это служит цели достаточно хорошо:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)
      for index,val in enumerate(ints,start=1):
  print(f"item #{index} = {val}")

Используйте enumerate для перебора списка

      ints = [8, 23, 45, 12, 78]
for idx,val in enumerate(ints):
    print('item #{} = {}'.format(idx+1, val))

Выход:

      item #1 = 8
item #2 = 23
item #3 = 45
item #4 = 12
item #5 = 78
Другие вопросы по тегам