Доступ к индексу в циклах 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)
Надеюсь это поможет.
Как правило, в 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
В вашем вопросе вы пишете "как мне получить доступ к индексу цикла, от 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