【发布时间】:2014-08-09 00:18:55
【问题描述】:
如何让 Python 的enumerate 函数从大数到小数(降序、递减、倒计时)?或者一般来说,如何在enumerate中使用不同的步长增量/减量?
例如,这样的函数,应用于列表['a', 'b', 'c'],起始值为10,步骤为-2,将产生迭代器[(10, 'a'), (8, 'b'), (6, 'c')]。
【问题讨论】:
如何让 Python 的enumerate 函数从大数到小数(降序、递减、倒计时)?或者一般来说,如何在enumerate中使用不同的步长增量/减量?
例如,这样的函数,应用于列表['a', 'b', 'c'],起始值为10,步骤为-2,将产生迭代器[(10, 'a'), (8, 'b'), (6, 'c')]。
【问题讨论】:
我没有找到比编写一个简单的生成器更优雅、惯用和简洁的方法:
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)]
如果你不明白上面的代码,请阅读What does the "yield" keyword do in Python?和Difference between Python's Generators and Iterators。
【讨论】:
一种选择是将zip 您的可迭代对象设置为range:
for index, item in zip(range(10, 0, -2), ['a', 'b', 'c']):
...
这确实有一个限制,您需要知道range 应该走多远(它应该覆盖的最小值 - 在我的示例中,超出部分将被zip 截断)。
如果您不知道,您可以滚动自己的“infinite range”并使用它:
>>> 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')]
【讨论】:
这是一种惯用的方法:
list(zip(itertools.count(10,-2), 'abc'))
返回:
[(10, 'a'), (8, 'b'), (6, 'c')]
【讨论】:
另一种选择是使用itertools.count,这有助于在reverse中通过step“枚举”。
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)【讨论】:
可能不是很优雅,使用 f'strings 下面的快速解决方案会很方便
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。