Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中带计数器的for循环?_Python_For Loop - Fatal编程技术网

python中带计数器的for循环?

python中带计数器的for循环?,python,for-loop,Python,For Loop,如何使用计数器创建for循环?我有一个列表,我想在每个n元素之后读取一个元素。我最初是这样做的 for i in enumerate(n): print(i) 但正如预期的那样,它打印每个元素而不是每个第n个元素,Python解决这个问题的方法是什么?只需使用一个范围: for i in range(0, size, n): print (i) 使用将迭代限制到每个n-th对象,这至少是任何其他建议解决方案的两倍: from itertools import islice

如何使用计数器创建for循环?我有一个列表,我想在每个
n
元素之后读取一个元素。我最初是这样做的

for i in enumerate(n):
    print(i)
但正如预期的那样,它打印每个元素而不是每个第n个元素,Python解决这个问题的方法是什么?

只需使用一个范围:

for i in range(0, size, n):
    print (i)
使用将迭代限制到每个
n
-th对象,这至少是任何其他建议解决方案的两倍:

from itertools import islice

n = 5
for ob in islice(iterable, None, None, n):
    print(ob)
从第一个对象开始,上面有效地生成第五个对象:

>>> from itertools import islice
>>> from string import ascii_uppercase as iterable
>>> n = 5
>>> for ob in islice(iterable, None, None, n):
...     print(ob)
...
A
F
K
P
U
Z
如果要跳到
n
th对象作为第一个要使用的对象,请将第一个
None
替换为
n-1

>>> for ob in islice(iterable, n - 1, None, n):
...     print(ob)
...
E
J
O
T
Y
没有创建输入序列的副本来实现这一点,因此不需要额外的内存或时间来生成结果。对每个
n
-th对象进行模数测试比对
enumerate()
中的索引进行模数测试更有效,或者使用
range()
生成索引。这是因为不需要进一步的Python字节码步骤来进行这些额外的测试或索引操作

如果还需要以这种方式选择项的索引,请通过包装iterable将
enumerate()
添加回:

>>> for i, ob in islice(enumerate(iterable), n - 1, None, n):
...     print(i, ob)
...
4 E
9 J
14 O
19 T
24 Y
islice()

>>> from timeit import timeit
>>> from itertools import islice
>>> import random
>>> testdata = [random.randrange(1000) for _ in range(1000000)]  # 1 million random numbers
>>> def islice_loop(it):
...     for ob in islice(it, None, None, 5): pass
...
>>> def range_loop(it):
...     for i in range(0, len(it), 5): ob = it[i]
...
>>> def slice_loop(it):
...     for ob in it[::5]: pass
...
>>> def enumerate_test_loop(it):
...     for i, ob in enumerate(it):
...         if i % 5 == 0: pass
...
>>> def enumerate_list_slice_loop(it):
...     for i, ob in list(enumerate(it))[::5]: pass
...
>>> timeit('tf(t)', 'from __main__ import testdata as t, islice_loop as tf', number=1000)
4.194277995004086
>>> timeit('tf(t)', 'from __main__ import testdata as t, range_loop as tf', number=1000)
11.904250939987833
>>> timeit('tf(t)', 'from __main__ import testdata as t, slice_loop as tf', number=1000)
8.32347785399179
>>> timeit('tf(t)', 'from __main__ import testdata as t, enumerate_list_slice_loop as tf', number=1000)
198.1711291699903

因此,对于100万个输入和1000个测试,
enumerate()
方法花费的时间是
islice()
版本的16倍,而
list(enumerate(…)[::n]
复制和切片操作花费了近3分钟来运行1000个测试,执行时间几乎慢了50倍。永远不要使用那个选项

我不确定哪种值是
n
,但通常有以下几种方法:(对我来说,
n
是一个列表)

其他方法可以是:

for index in range(0, len(n), nth): # Only work with sequences
   print(n[index]) # If the output is not like you want, try doing n[index + 1]
或:

即使您可以将第一个与最后一个合并:

for i, item in list(enumerate(n))[::nth]: # Huge low perfomance warning!!!
    print(item)
但我不确定这是否有优势

此外,如果您愿意创建一个函数,可以执行类似于
枚举
函数的操作:

def myEnumerate(sequence, start=0, jump=1):
    n = start
    j = start // Or j = 0, that is your decision.
    for elem in sequence:
        if j % jump == 0:
            yield n, elem
            n += 1
        j += 1

for index, item in myEnumerate(n, jump=1):
    print(item)
就我个人而言,我不会做最后一个。我不知道为什么,但这是一种感觉

性能测试
但是如果你真的在寻找性能,你应该阅读。

枚举
返回一个元组序列,看起来像
(索引,值)

假设您的列表是
my_list
。你可以这样做

for index, value in enumerate(my_list):
    if index % n == 0: #it's an nth item
        print(value)
这是python向for循环添加索引的方法

一些备选方案

如果您的目标是按n对列表元素执行某些操作,那么以下是一些替代解决方案,它们不一定会向循环中添加索引,但会让您达到需要的位置:

阵列切片

您还可以使用带有步骤的数组切片

nth_elements = my_array[0::n]
for e in nth_elements:
    print(e)
这样做的好处是,您现在使用的列表更小,但需要消耗更多的内存和制作副本的时间,但如果您使用它执行多个操作,这可能会更有利。它写起来很快,读起来也很容易

范围

你可以做一些类似于范围函数的事情

for index in range(0, len(my_list), n):
    print(n)
注意:如果您使用的是python2,最好使用
xrange

这只是得到索引,而不是索引和值。它速度快,内存效率高
range
(或
xrange
)是惰性的,您直接在数组中使用索引,因此不必触摸每个元素

Itertools

如果您想要一个惰性序列,可以使用
itertools
。如果子序列太大,无法方便地放入内存,那么这可能很有用

from itertools import islice
for element in islice(my_list, 0, len(my_list), n):
    print(element)

这是快速和内存有效的,但它需要导入。当然,它来自标准库,但如果您正在为小型设备编写代码,可能它不可用。

对于i,枚举(n)中的项:
i
是您的计数器。例如,使用范围(0,len(您的列表),n)。
enumerate()
基本上用于迭代列表中的项目以及访问其索引。我不确定在添加步骤后是否需要新的索引编号。然后是的,您可以将切片和枚举结合起来,例如:
用于索引,枚举中的值(n[::n]):print(index,value)
(但它会消耗内存,因为它是一个副本)我不是下选程序,也不认为它值得,但用它来代替步长为
的范围()
,有什么问题要回避,或者OP的标题实际上是问谁要在循环中添加计数器?@roganjosh:我不清楚OP为什么要使用
enumerate()
调用;如果它只是用来解决他们问题的一部分,那么这里就不再需要它了
islice()
将比其他解决方案更有效。@roganjosh:如果您确实想添加索引,那么只需将
iterable
替换为
enumerate(iterable)
,您也可以获得单个索引,但效率更高。这只会生成索引,并假定一个序列作为输入(具有设置的长度)。您必须使用
sequence[i]
来获取输入序列的实际
n
-th值。切片将为您提供输入列表对象的副本。
range()
和slice选项都只对序列有效,只对iterables有效(这是
enumerate()
版本所能做到的)。@MartijnPieters我知道切片会给你一个副本,这有问题吗?我也知道我的想法并不适用于所有事情。这就是为什么我说通常工作。但我不能给出更好的答案,因为我缺乏知识:)若输入太大,或者这部分代码在代码的关键部分(复制需要时间),创建副本可能是一个问题。@MartijnPieters你们说得对。我没有说,因为我认为他会做一些小事情,但我应该把它添加到我的答案中。我现在正在编辑,我不知道
nth_elements = my_array[0::n]
for e in nth_elements:
    print(e)
for index in range(0, len(my_list), n):
    print(n)
from itertools import islice
for element in islice(my_list, 0, len(my_list), n):
    print(element)