在“for”循环中访问索引

Accessing the index in 'for' loops

提问人:Joan Venge 提问时间:2/7/2009 最后编辑:cottontailJoan Venge 更新时间:8/26/2023 访问量:4249569

问:

如何在循环遍历序列时访问索引?for

xs = [8, 23, 45]

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

期望输出:

item #1 = 8
item #2 = 23
item #3 = 45
Python 循环 列表

评论

109赞 plugwash 10/3/2018
请注意,python 中的索引从 0 开始,因此示例列表的索引是 0 到 4,而不是 1 到 5

答:

136赞 David Hanak 2/7/2009 #1
for i in range(len(ints)):
   print(i, ints[i]) # print updated to print() in Python 3.x+ 

评论

11赞 Ben Blank 2/7/2009
这可能应该是 3.0 之前的。xrange
67赞 saulspatz 8/2/2015
请改用枚举
5赞 januarvs 3/15/2017
对于上面的 Python 2.3,请使用 enumerate 内置函数,因为它更像 Python。
2赞 adg 4/1/2017
枚举并不总是更好 - 这取决于应用程序的要求。在我目前的情况下,对象长度之间的关系对我的应用程序很有意义。虽然我一开始使用的是枚举,但我改用这种方法是为了避免编写逻辑来选择要枚举的对象。
4赞 chepner 9/16/2017
@adg 我不明白避免如何保存任何逻辑;你仍然需要选择要索引的对象,不是吗?enumeratei
47赞 Charlie Martin 2/7/2009 #2

老式方式:

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

评论

5赞 7/30/2018
没有错,用于 C/C++ 和其他语言。它被认为是非 pythonic,但也可以在 python 中使用。就像简单的解决方案一样,将其分解为源头:+
0赞 7/30/2018
一些蟒蛇极端分子会说,不要这样做。但我这么说只是为了表明有不止一种可能的方法
8779赞 Mike Hordecki 2/7/2009 #3

使用内置函数 enumerate():

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

通过手动索引或手动管理其他状态变量是非 pythonic 的。for i in range(len(xs)): x = xs[i]

查看 PEP 279 了解更多信息。

评论

143赞 clozach 4/1/2018
正如 Aaron 在下面指出的,如果你想得到 1-5 而不是 0-4,请使用 start=1。
10赞 TheRealChx101 10/18/2019
不会产生其他开销?enumerate
10赞 Błotosmętek 2/7/2020
@TheRealChx101根据我的测试(Python 3.6.3),差异可以忽略不计,有时甚至有利于 .enumerate
25赞 ShadowRanger 10/7/2020
@TheRealChx101:它低于每次循环和索引的开销,也低于手动跟踪和单独更新索引的开销。 with 解包经过大量优化(如果 S 被解压缩为名称,如提供的示例所示,它会重用相同的 Each 循环,以避免 freelist 查找的成本,它有一个优化的代码路径,用于当索引适合时执行廉价的寄存器内数学运算,绕过 Python 级别的数学运算,并且它避免在 Python 级别索引, 这比你想象的要贵)。rangeenumeratetupletuplessize_tlist
8赞 bfris 10/15/2021
@user2585501。它确实:或者将执行遍历索引的普遍常见操作。但是,如果你同时想要项目索引,这是一个非常有用的语法。我一直在使用它。for i in range(5)for i in range(len(ints))enumerate
18赞 thinker007 5/5/2012 #4

根据这个讨论:对象的列表索引

循环计数器迭代

当前用于循环索引的习惯使用内置函数: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 – 循环计数器迭代

评论

24赞 Tadeck 4/1/2013
这不适用于遍历生成器。只需使用 enumerate()。
2赞 TankorSmash 8/16/2016
如今,当前的成语是枚举,而不是范围调用。
0赞 Jean-François Fabre 4/20/2019
这与旧的答案相同:stackoverflow.com/a/522576/6451573
261赞 A.J. 5/27/2014 #5

从以下位置开始非常简单:10

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+
   

评论

16赞 Antti Haapala -- Слава Україні 3/18/2016
问题是关于列表索引的;由于它们从 0 开始,因此从其他数字开始几乎没有意义,因为索引是错误的(是的,OP 在问题中也说错了)。否则,如您所指出的,调用元组 just 的变量会非常具有误导性。只需使用 .index, itemindexfor index, item in enumerate(ints)
1赞 hygull 1/2/2018
更好的方法是将索引括在括号对内为 (index),它将在 Python 版本 2 和 3 上都有效。
2赞 pushkin 12/1/2018
@AnttiHaapala 我认为,原因是问题的预期输出从索引 1 而不是 0 开始
0赞 ShadowRanger 10/7/2020
@hygull:变成不会改变 Py2 或 Py3 上的事情。我觉得也许你正在考虑改成;使其在 Py2 和 Py3 上都起作用的唯一方法是添加到文件顶部以获得一致的 Py3 样式,并将 .或者您阅读了该问题的早期编辑,原始时间是什么时候,没有解压缩为两个名称,但是如果您未能解压缩,括号仍然不会更改任何内容。index(index)printfrom __future__ import print_functionprintprintprint(index, item)indextuple
1290赞 Russia Must Remove Putin 1/22/2015 #6

使用 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'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 代码之间差异的典型示例。惯用代码是复杂(但不复杂)的 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')

我们可以使用所谓的“序列解包”来从这个二元组中提取元素:

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

当我们检查时,我们发现它指的是第一个索引 0,并引用了第一项。indexitem'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)

评论

4赞 Bergi 2/22/2020
获取计数”示例在为空时是否有效?items
3赞 ShadowRanger 10/7/2020
@Bergi:它不会,但你可以在循环之前添加以确保它有一个值(当循环从未赋值时,它是正确的值,因为根据定义没有项目)。count = 0count
2赞 nerak99 8/18/2022
精彩而全面的答案,解释了惯用语(又名pythonic)之间的区别,而不仅仅是说特定方法是单调的(即非pythonic)而不加解释。
21赞 rassa45 5/25/2015 #7

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

for x in range(0, 5):

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

要获取索引的值,请使用

list[index]
19赞 Liam 5/25/2015 #8

您可以使用以下代码来完成:

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
47赞 Andriy Ivaneyko 8/4/2016 #9

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

Python 3.7 中访问循环中列表索引的最快方法是对小型、中型和大型列表使用 enumerate 方法

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

# 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

因此,当索引需要时,using method 是迭代速度最快的方法。enumerate

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

评论

7赞 3/4/2017
“可读性很重要” 小 <1000 范围内的速度差异微不足道。在已经很小的时间指标上,它慢了 3%。
0赞 Georgy 5/22/2019
更新 Python 3 的答案怎么样?
2赞 Andriy Ivaneyko 6/16/2020
@Georgy有道理,在 Python 3.7 上枚举是完全赢家:)
66赞 Charitoo 8/15/2017 #10

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

  1. 使用 enumerate(被认为是最惯用的)

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

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

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

for index in range(len(lst)):   # or xrange
    # you will have to write extra code to get the element
  1. 创建一个变量来保存索引(使用 while)

index = 0
while index < len(lst):
    # You will have to write extra code to get the element
    index += 1  # escape infinite recursion
  1. 总有另一种方式

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

12赞 Ashok Kumar Jayaraman 2/7/2018 #11

您也可以尝试以下操作:

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']
-7赞 Sumit Kumar 4/24/2018 #12

这很好地达到了目的:

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

评论

16赞 Peter Szoldan 5/16/2018
如果列表中有重复的元素,这将崩溃,就像搜索第一次出现的 一样,没有提到查找每个元素所需的 O( n^2 ) 时间。index()x
0赞 Sumit Kumar 6/6/2018
完全同意它不适用于列表中的重复元素。毕竟我也在学习python。
0赞 Peter Mortensen 4/20/2022
用户 Raj kumar 接受的建议编辑导致错误“NameError: name 'list1' is not defined”
6赞 lola 4/24/2018 #13

要使用 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)]
8赞 PyRsquared 5/31/2018 #14

您可以使用以下方法:index

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

注释中突出显示,如果 中存在重复项,则此方法不起作用。以下方法应适用于以下任何值:intsints

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

它使用 in the selected answer to this question, but with list comprehension, make it faster with less code.enumerate

18赞 Ankur Kothari 6/4/2018 #15

如果我要迭代,我会这样做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])
13赞 RIshu 6/10/2018 #16

如果列表中没有重复值:

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

评论

2赞 Stam Kaly 12/19/2018
请注意,不应使用第一个选项,因为仅当序列中的每个项目都是唯一的时,它才能正常工作。
6赞 4/20/2019
第一个选项是 O(n²),这是一个糟糕的主意。如果您的列表长度为 1000 个元素,则花费的时间实际上是使用 .您应该删除此答案。enumerate
18赞 DrM 8/16/2018 #17

在您的问题中,您写道“我如何访问循环索引,在本例中为 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=nenumerate()

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

其输出为

1 1
2 2
3 3
4 4
5 5
133赞 Andy Jazz 1/17/2019 #18

在 Python 3.12 上测试

这里有 12 个示例,说明如何使用 for 循环while 循环和一些循环函数访问索引及其相应数组的元素。请注意,默认情况下,数组索引始终从零开始(请参阅更改此设置)。example 4

1.带有计数器和运算符的循环元素。+=

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

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

Result:

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

Result:

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

Result:

#    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. 您可以将该值更改为任何增量。index

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

for i, item in enumerate(items, start=100):
    print(i, item)

Result:

#    100 8
#    101 23
#    102 45
#    103 12
#    104 78

5.使用方法自动计数器增量。range(len(...))

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

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

Result:

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

6.使用loop inside功能。for

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

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

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

Result:

#    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

Result:

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

8. 返回 Generator 对象的语句。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)

Result:

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

9. 带有循环和 .forlambda

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

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

Result:

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

10. 使用 Python 的函数一次遍历两个列表。zip()

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

for index in range(len(items)):
    indices.append(index)

for item, index in zip(items, indices):
    print("{}: {}".format(index, item))

Result:

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

11. 使用循环和 & 方法遍历 2 个列表。whileiter()next()

items = [8, 23, 45, 12, 78]
indices = range(len(items))

iterator1 = iter(indices)
iterator2 = iter(items)
  
try:
    while True:
        i = next(iterator1)
        element = next(iterator2)
        print(i, element)
except StopIteration:
    pass

Result:

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

12. 另外,在类中迭代列表的元素也很好。Static Method

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

class ElementPlus:
    @staticmethod                            # decorator
    def indexForEachOfMy(iterable):
        for pair in enumerate(iterable):
            print pair

ElementPlus.indexForEachOfMy(items)

Result:

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

评论

1赞 zomilanovic 8/14/2023
感谢您提供非常详细的答案,展示了如何实现这一目标的所有变体。在我看来,应该是公认的答案!
8赞 Amar Kumar 4/19/2020 #19

使用 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

评论

0赞 Peter Mortensen 4/20/2022
请查看我们是否应该编辑问题以将代码从图像转录为文本? 和 为什么在提问时不上传代码/错误的图像? (例如,“图像只能用于说明无法通过任何其他方式阐明的问题,例如提供用户界面的屏幕截图。 并采取适当的行动(它也包括答案)。提前致谢。
6赞 Rahul 5/10/2021 #20

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

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

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

这是一种简单的方法:

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

一个循环,其中“counter”变量设置为初始值设定项,该初始值设定器将是一个参数,在格式化字符串时,作为项目编号。

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

评论

0赞 LunaticXXD10 1/8/2022
@calculuswhiz while 循环是一个重要的代码片段。首字母缩写器“计数器”用于项目编号。关于缩进:这个人必须对编程有足够的了解,缩进很重要。所以在你做完你的特殊属性之后......{copy paste} 您仍然可以编辑缩进。代码运行得非常好,很流畅
1赞 General Grievance 1/10/2022
@LunaticXXD10 在原始帖子中(您可以在编辑历史记录中看到)中,缩进的级别与循环相同。在这种情况下,它将在循环的每次迭代中更新。在这里,它会在循环的每次迭代中更新。我在循环中的问题仍然是:当计数器可以在循环中更新时,为什么需要使用 while 循环?这在拉胡尔的回答中清晰可见。counter += 1forforwhilewhilefor
1赞 Peter Mortensen 4/20/2022
回复“......必须对缩进很重要的编程有足够的了解“:嗯,计算机是字面意思的。
0赞 kamalesh d 5/12/2022 #23

可以通过以下代码实现:

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
2赞 Ran Turner 6/8/2022 #24

您可以使用然后像这样查找索引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))
3赞 jglad 10/16/2022 #25

除了上面所有优秀的答案之外,这里还有在使用 pandas Series 对象时这个问题的解决方案。在许多情况下,pandas 系列具有无法使用函数访问的自定义/唯一索引(例如,唯一标识符字符串)。enumerate()

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

我们可以在 for 循环中使用 pandas Series 的索引:.items()

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

输出:

#    id #G923002 = 8
#    id #G923004 = 23
#    id #G923005 = 45
3赞 Maifee Ul Asad 11/5/2022 #26

单行爱好者:

[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 不提供索引;如果您正在使用listfor
  • 如果你一个,它会返回你另一个enumeratelistlist
    • 但是该列表将具有不同的类型
    • 它将用索引包装每个元素tuple
    • 我们可以将元组作为变量访问,用逗号(,)

谢谢。求你让我在你们的祷告中。

4赞 cottontail 8/22/2023 #27

在 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

另一种方法是在循环内使用。但是,与此页上提及此方法的其他答案(123)相反,索引搜索的起点(即第二个参数)必须传递给该方法。这可以让你实现两件事:(1)不会从头开始重复列表;(2)可以找到所有值的索引,甚至是重复的索引。list.index()list.index()

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

在性能方面,如果您想要所有/大部分索引,是最快的选择。如果您只寻找特定的指数,那么可能会更有效。以下是两个更有效的例子。enumerate()list.index()list.index()

示例#1:特定值的索引

假设您要查找列表中出现特定值(例如最高值)的所有索引。例如,在以下示例中,我们希望查找出现 2 的所有索引。这是使用 .但是,我们也可以通过在 while 循环中使用该方法来搜索 2 的索引;如前所述,在每次迭代中,我们从上一次迭代中中断的位置开始索引搜索。enumerate()list.index()

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]

事实上,在某些情况下,它比产生相同输出的选项要快得多,尤其是在列表很长的情况下。enumerate()

示例#2:小于目标的第一个数字的索引

在循环中经常需要索引的另一个常见练习是查找列表中满足某些条件(例如大于/小于某个目标值)的第一项的索引。在以下示例中,我们希望查找超过 2.5 的第一个值的索引。这是一个单行使用,但使用更有效,因为获取不会使用的索引是有成本的(不会产生)。enumerate()list.index()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)

benchmark


用于生成运行时速度比图的代码:

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

评论

1赞 Kelly Bundy 8/24/2023
干得好。尽管有两次通过,但 index() 在第二种情况下击败 enumerate() 是我已经告诉/向人们展示过几次的东西,从现在开始我可能会在这里指出它们:-)