Python如何实现向下或使用自定义步长枚举?

24
如何使Python的enumerate函数从大到小枚举(降序,递减,倒数)?或者说,如何在enumerate中使用不同的步长增量/减量?
例如,应用于列表['a','b','c']的此类函数,其起始值为10,步长为-2,将生成迭代器[(10,'a'),(8,'b'),(6,'c')]
6个回答

33

我还没有找到比编写一个简单的生成器更优雅、惯用和简洁的方法:

def enumerate2(xs, start=0, step=1):
    for x in xs:
        yield (start, x)
        start += step

例子:

>>> list(enumerate2([1,2,3], 5, -1))
[(5, 1), (4, 2), (3, 3)]
>>> list(enumerate2([1,2,3], 5, -2))
[(5, 1), (3, 2), (1, 3)]

如果您不理解上述代码,请阅读Python中"yield"关键字的作用Python生成器与迭代器的区别


10

一种选择是将您的可迭代对象与 range 进行 zip

for index, item in zip(range(10, 0, -2), ['a', 'b', 'c']):
    ...

这种方法的限制是你需要知道 range 应该覆盖的最小范围(如我的示例,过剩部分将被 zip 截断)。

如果你不知道,你可以自己创建一个“无限 range”(或者只需使用 itertools.count),并使用它:

>>> def inf_range(start, step):
    """Generator function to provide a never-ending range."""
    while True:
        yield start
        start += step

        
>>> list(zip(inf_range(10, -2), ['a', 'b', 'c']))
[(10, 'a'), (8, 'b'), (6, 'c')]

3

这里有一种惯用的方法:

list(zip(itertools.count(10,-2), 'abc'))

returns: [(10, 'a'), (8, 'b'), (6, 'c')]


2
另一个选择是使用 itertools.count,它有助于通过步长倒序方式进行“枚举”。
import itertools

counter = itertools.count(10, -2)
[(next(counter), letter) for letter in ["a", "b", "c"]]
# [(10, 'a'), (8, 'b'), (6, 'c')]

特点

  • 简洁明了
  • 步骤和方向逻辑储存在count()中,非常紧凑
  • 枚举索引使用next()进行迭代
  • count()天生是无限的;如果边界未知,则很有用(参见@jonrsharpe)
  • 序列长度本质上终止了这个无限迭代器

0

如果您不需要将迭代器保留在变量中,只需遍历某些容器,请将索引乘以步长。

container = ['a', 'b', 'c']
step = -2

for index, value in enumerate(container):
    print(f'{index * step}, {value}')


>>> 0, a
-2, b
-4, c

-1
也许不太优雅,但使用f字符串,以下的快速解决方案可能会很方便。
my_list = ['apple', 'banana', 'grapes', 'pear']
p=10
for counter, value in enumerate(my_list):
    print(f" {counter+p}, {value}")
    p+=9

> 10, apple
> 20, banana
> 30, grapes
> 40, pear

这种写法似乎有些复杂了,其实就是 (counter + 1)*10 的另一种表达方式。 - MisterMiyagi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接