在“for”循环中访问索引

问题描述:

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

xs = [8, 23, 45]

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

期望的输出:

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

解决方案1:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

使用内置函数 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 是一个 非常 有用的语法。我用它所有的时间。

解决方案2:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

使用 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 时,它是正确的值,因为根据定义没有项目)。

解决方案3:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

从 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 时,您阅读了问题的早期编辑,未解压缩为两个名称,但如果您未能解压缩,括号仍然不会改变任何内容。

解决方案4:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

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 索引的对象,不是吗?

解决方案5:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

正如 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 一起使用。它比其他示例更好地处理嵌套循环。

解决方案6:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

以下是使用 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

  1. 使用 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)

  1. 分别使用索引和值。
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

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

  1. 当然,我们不能忘记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

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

  1. 带有 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)]

解决方案7:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

老套路:

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

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

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

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

解决方案8:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

在 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 上,枚举是总赢家:)

解决方案9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

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

这是一个简单的方法:

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

解决方案10:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

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

for x in range(0, 5):

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

要获取索引的值,请使用

list[index]

解决方案11:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

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

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

原文链接:https://www.huntsbot.com/qa/g17k/accessing-the-index-in-for-loops?lang=zh_CN

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值