在“for”循环中访问索引

python loops list

如何在 for 循环中访问索引?

xs = [8, 23, 45]

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

期望的输出:

item #1 = 8
item #2 = 23
item #3 = 45

请注意,python 中的索引从 0 开始,因此示例列表的索引是 0 到 4 而不是 1 到 5

M
Mateen Ulhaq

使用内置函数 enumerate()

for idx, x in enumerate(xs):
    print(idx, x)

non-pythonic 通过 for i in range(len(xs)): x = xs[i] 手动索引或手动管理附加状态变量。

查看PEP 279了解更多信息。

正如 Aaron 在下面指出的那样,如果您想获得 1-5 而不是 0-4,请使用 start=1。

enumerate 不会产生其他开销吗?

@TheRealChx101 根据我的测试(Python 3.6.3),差异可以忽略不计,有时甚至支持 enumerate

@TheRealChx101:它低于每次循环 range 和索引的开销,也低于单独手动跟踪和更新索引的开销。带解包的 enumerate 进行了高度优化(如果将 tuple 解包为提供的示例中的名称,它会在每个循环中重用相同的 tuple 以避免甚至空闲列表查找的成本,它具有优化的代码路径当索引适合执行廉价的寄存器内数学运算的 ssize_t 时,绕过 Python 级别的数学运算,并且它避免在 Python 级别索引 list,这比您想象的要昂贵)。

@用户2585501。它确实:for i in range(5)for i in range(len(ints)) 将执行迭代索引的普遍常见操作。但是,如果您希望项目 都是索引,则 enumerate 是一个 非常 有用的语法。我用它所有的时间。

R
Russia Must Remove Putin

使用 for 循环,我如何访问循环索引,在这种情况下从 1 到 5?

在迭代时使用 enumerate 获取元素的索引:

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

请注意,Python 的索引从零开始,所以你会得到 0 到 4 上面。如果您想要计数,从 1 到 5,请执行以下操作:

count = 0 # in case items is empty and you need it after the loop
for count, item in enumerate(items, start=1):
    print(count, item)

统一的控制流

您要求的是以下 Pythonic 等价物,这是大多数低级语言程序员会使用的算法:

index = 0 # Python 的索引从零开始 for item in items: # Python 的 for 循环是一个“for each”循环 print(index, item) index += 1

或者在没有 for-each 循环的语言中:

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

或者有时在 Python 中更常见(但不习惯):

对于范围内的索引(len(items)):打印(索引,项目[索引])

使用枚举函数

Python 的 enumerate function 通过隐藏索引的说明来减少视觉上的混乱,并将可迭代对象封装到另一个可迭代对象(enumerate 对象)中,从而生成索引的两项元组和原始可迭代对象将提供的项。看起来像这样:

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

此代码示例很好地说明了 Python 惯用代码与非 Python 惯用代码之间的差异canonical示例。惯用代码是复杂(但不复杂)的 Python,以预期使用的方式编写。该语言的设计者期望使用惯用代码,这意味着通常该代码不仅更具可读性,而且更高效。

计数

即使您不需要索引,但您需要计算迭代次数(有时是可取的),您可以从 1 开始,最终数字将是您的计数。

count = 0 # in case items is empty
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')

我们可以使用所谓的“sequence unpacking”从这个二元组中提取元素:

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

当我们检查 index 时,我们发现它指的是第一个索引 0,而 item 指的是第一个项目 'a'

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

结论

Python 索引从零开始

要在迭代时从可迭代对象中获取这些索引,请使用 enumerate 函数

以惯用的方式使用 enumerate(以及元组解包)创建的代码更具可读性和可维护性:

所以这样做:

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

items 为空时,“获取计数”示例是否有效?

@Bergi:不会,但是您可以在循环之前添加 count = 0 以确保它具有值(当循环从未分配给 count 时,它是正确的值,因为根据定义没有项目)。

S
SuperStormer

0 以外的 1 开始非常简单:

for index, item in enumerate(iterable, start=1):
   print index, item  # Used to print in python<3.x
   print(index, item) # Migrate to print() after 3.x+
   

问题是关于列表索引;因为它们从 0 开始,所以从其他数字开始没有什么意义,因为索引是错误的(是的,OP 在问题中也说错了)。否则,正如您所指出的,仅将 index, item 的元组变量称为 index 是非常具有误导性的。只需使用 for index, item in enumerate(ints)

更好的做法是将括号内的索引作为 (index) 括起来,它适用于 Python 版本 2 和 3。

@AnttiHaapala 我认为原因是问题的预期输出从索引 1 开始而不是 0

@hygull:将 index 变成 (index) 不会改变 Py2 或 Py3 上的任何事情。我觉得您可能正在考虑更改为 print;在 Py2 和 Py3 上实现该功能的唯一方法是将 from __future__ import print_function 添加到文件顶部以获得一致的 Py3 样式 print,并将 print 更改为 print(index, item)。或者,当 index 是原始 tuple 时,您阅读了问题的早期编辑,未解压缩为两个名称,但如果您未能解压缩,括号仍然不会改变任何内容。

m
mhhabib
for i in range(len(ints)):
   print(i, ints[i]) # print updated to print() in Python 3.x+ 

对于 3.0 之前的版本,这可能应该是 xrange

改为使用枚举

对于上面的 Python 2.3,使用 enumerate 内置函数,因为它更 Pythonic。

枚举并不总是更好 - 它取决于应用程序的要求。在我目前的情况下,对象长度之间的关系对我的应用程序很有意义。虽然我开始使用枚举,但我切换到这种方法以避免必须编写逻辑来选择要枚举的对象。

@adg 我看不出避免 enumerate 如何保存任何逻辑;您仍然必须选择要使用 i 索引的对象,不是吗?

P
Peter Mortensen

正如 Python 中的规范一样,有几种方法可以做到这一点。在所有示例中假设:lst = [1, 2, 3, 4, 5]

使用枚举(被认为是最惯用的)

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

在我看来,这也是最安全的选择,因为已经消除了进入无限递归的机会。项目及其索引都保存在变量中,无需编写任何进一步的代码来访问该项目。

创建一个变量来保存索引(使用for)

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

创建一个变量来保存索引(使用while)

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

总有另一种方式

如前所述,还有其他方法可以做到这一点,这里没有解释,它们甚至可能更适用于其他情况。 例如,将 itertools.chain 与 for 一起使用。它比其他示例更好地处理嵌套循环。

A
Andy Jazz

以下是使用 for-in 循环访问索引和数组元素的方法。

1. 使用计数器和 += 运算符循环元素。

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

for value in items:
    print(counter, value)
    counter += 1

结果:

#    0 8
#    1 23
#    2 45
#    3 12
#    4 78

2. 使用 enumerate() 方法循环元素。

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)

3. 分别使用索引和值。

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

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

结果:

#    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

4.您可以将索引号更改为任何增量。

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

for i, value in enumerate(items, start=1000):
    print(i, value)

结果:

#    1000 8
#    1001 23
#    1002 45
#    1003 12
#    1004 78

5. 使用 range(len(...)) 自动增加计数器。

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

for i in range(len(items)):
    print("Index:", i, "Value:", items[i])

结果:

#    ('Index:', 0, 'Value:', 8)
#    ('Index:', 1, 'Value:', 23)
#    ('Index:', 2, 'Value:', 45)
#    ('Index:', 3, 'Value:', 12)
#    ('Index:', 4, 'Value:', 78)

6.在函数内部使用for-in循环。

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

def enum(items, start=0):
    counter = start

    for value in items:
        print(counter, value)
        counter += 1
    
enum(items)

结果:

#    0 8
#    1 23
#    2 45
#    3 12
#    4 78

7. 当然,我们不能忘记while循环。

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

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

结果:

#    0 8
#    1 23
#    2 45
#    3 12
#    4 78

8. yield 语句返回一个生成器对象。

def createGenerator():        
    items = [8, 23, 45, 12, 78]

    for (j, k) in enumerate(items):
        yield (j, k)
        

generator = createGenerator()

for i in generator:
    print(i)

结果:

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

9. 带有 for-in 循环和 lambda 的内联表达式。

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

xerox = lambda upperBound: [(i, items[i]) for i in range(0, upperBound)]
print(xerox(5))

结果:

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

老套路:

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

这没有错,并且在 C/C++ 和其他语言中使用。它被认为是非pythonic,但也可以在python中使用。就像将其分解为源的简单解决方案一样:+

一些 python 极端分子会说,不要这样做。但我说这只是为了表明有不止一种可能的方法

C
Community

访问索引和方法的性能基准测试

Python 3.7 中访问循环内列表索引的最快方法是将 enumerate method 用于小型、中型和大型列表。

请在下面的代码示例中查看可用于迭代列表和访问索引值及其性能指标(我认为这对您有用)的不同方法:

# Using range
def range_loop(iterable):
    for i in range(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("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 speed for list with 1000 items
measure(range(1000))
# range:  1.161622366
# enumerate:  0.5661940879999996
# manual_indexing:  0.610455682

# Measure speed for list with 100000 items
measure(range(10000))
# range:  11.794482958
# enumerate:  6.197628574000001
# manual_indexing:  6.935181098000001

# Measure speed for list with 10000000 items
measure(range(10000000), number=100)
# range:  121.416859069
# enumerate:  62.718909123
# manual_indexing:  69.59575057400002

因此,当需要索引时,使用 enumerate 方法是最快的迭代方法。

在下面添加一些有用的链接:

Python 2.X 中的 range 和 xrange 函数有什么区别?

在 Python 中使用 enumerate 的 for 循环或使用 xrange 的 for 循环哪个更快?

范围(len(list))还是枚举(list)?

“可读性很重要” <1000 范围内的速度差异是微不足道的。在已经很小的时间指标上,它慢了 3%。

如何更新 Python 3 的答案?

@Georgy 是有道理的,在 python 3.7 上,枚举是总赢家:)

L
Lars

您可以使用 enumerate 并在字符串文字中嵌入表达式来获得解决方案。

这是一个简单的方法:

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

首先,索引将从 0 到 4。编程语言从 0 开始计数;不要忘记这一点,否则您将遇到索引越界异常。在 for 循环中,您只需要一个从 0 计数到 4 的变量,如下所示:

for x in range(0, 5):

请记住,我写了 0 到 5,因为循环在最大值之前停止了一个数字。 :)

要获取索引的值,请使用

list[index]
L
Liam

您可以使用以下代码执行此操作:

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
P
Peter Mortensen

根据这个讨论:object's 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

通过 PEP 212 – Loop Counter Iteration

这不适用于迭代生成器。只需使用枚举()。

如今,当前的习惯用法是枚举,而不是范围调用。

它与旧答案相同:stackoverflow.com/a/522576/6451573

G
Georgy

在您的问题中,您写道“我如何访问循环索引,在这种情况下从 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

这将我们带到 enumerate()start=n 开关。这只是抵消了索引,您可以等效地简单地在循环内的索引中添加一个数字。

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

输出为

1 1
2 2
3 3
4 4
5 5
s
so2

如果我要迭代 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])
G
Georgy

如果列表中没有重复值:

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

请注意,不应使用第一个选项,因为它仅在序列中的每个项目都是唯一的情况下才能正常工作。

第一个选项是 O(n²),这是一个糟糕的主意。如果您的列表有 1000 个元素长,那么它实际上将比使用 enumerate 长 1000 倍。你应该删除这个答案。

A
Ashok Kumar Jayaraman

你也可以试试这个:

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']
P
Peter Mortensen

您可以使用 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 的方法,但具有列表理解,从而以更少的代码使其更快。

A
Amar Kumar

使用 while 循环的简单答案:

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

输出:

Item  1  =  8
Item  2  =  23
Item  3  =  45
Item  4  =  12
Item  5  =  78

请查看 Should we edit a question to transcribe code from an image to text?Why not upload images of code/errors when asking a question?(例如,“图片只能用于说明 可以'不要以任何其他方式明确, 例如提供用户界面的屏幕截图。”)并采取适当的action(它也包括答案)。提前致谢。

S
Sam

您可以简单地使用诸如 count 的变量来计算列表中的元素数量:

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

要使用 for 循环在列表推导中打印 (index, value) 元组:

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)]
R
Ran Turner

您可以使用 range(len(some_list)) 然后像这样查找索引

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

或者使用 Python 的内置 enumerate 函数,该函数允许您遍历列表并检索列表中每个项目的索引和值

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

可以通过以下代码实现:

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

这里,range(1, len(xs)+1);如果您希望输出从 1 而不是 0 开始,则需要从 1 开始范围并将 1 添加到估计的总长度,因为默认情况下 python 从 0 开始索引数字。

Final Output:
item #1 = 8
item #2 = 23
item #3 = 45
P
Peter Mortensen

将“计数器”变量设置为初始化程序的循环,该变量将作为参数,在格式化字符串时作为项目编号。

for 循环访问作为列表的“listos”变量。当我们通过“i”访问列表时,“i”被格式化为商品价格(或任何价格)。

listos = [8, 23, 45, 12, 78]
counter = 1
for i in listos:
    print('Item #{} = {}'.format(counter, i))
    counter += 1

输出:

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

@calculuswhiz while 循环是一个重要的代码片段。初始化程序“计数器”用于项目编号。关于缩进:这个人必须对缩进很重要的编程有足够的了解。所以在你做了你的特殊属性之后...... {复制粘贴}你仍然可以编辑缩进。并且代码运行得非常流畅

@LunaticXXD10 在您的原始帖子中,您可以在编辑历史记录中看到,counter += 1for 循环在同一级别缩进。在这种情况下,它会在 for 循环的每次迭代中更新。在这里,它在 while 循环的每次迭代中更新。我对 while 循环的问题仍然存在:当计数器可以在 for 循环中更新时,为什么需要使用 while 循环?这在 Rahul's answer 中显而易见。

重新“......必须对缩进很重要的编程有足够的了解”:嗯,计算机是真正意义上的。

P
Peter Mortensen

这很好地达到了目的:

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

如果列表中有重复的元素,这将分解,因为 index() 将搜索 x 的第一次出现,更不用说 O( n^2 )查找每个元素所需的时间。

完全同意它不适用于列表中的重复元素。毕竟我也在学习python。

用户 Raj kumar 接受的建议编辑导致错误“NameError: name 'list1' is not defined”