第一个想到的是:
>>> l = list('abcdef')
>>> for i in range(len(l)-1, -1, -1):
... item = l[i]
... print(i, item)
...
5 f
4 e
3 d
2 c
1 b
0 a
我尝试使用以下内容:
>>> l
['a', 'b', 'c', 'd', 'e', 'f']
>>> for i,ch in reversed(enumerate(l)):
... print(i,ch)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'enumerate' object is not reversible
但显然“枚举”对象是不可逆的。我可以用以下方法欺骗它:
>>> for i,ch in reversed(list(enumerate(l))):
... print(i,ch)
...
5 f
4 e
3 d
2 c
1 b
0 a
但这感觉不太对——有点麻烦。有一个更好的方法吗?也许一些
inverse_enumerate
隐藏的是像集合或 itertools 这样的库?
这可能不是最Pythonic的方法,但您可以重用enumerate
enumerate
。
该文档提供了以下代码:
def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1
这里是一个
renumerate
函数的提案,它以相反的顺序生成序列的元素:
def renumerate(sequence, start=None):
n = start
if start is None:
n = len(sequence) - 1
for elem in sequence[::-1]:
yield n, elem
n -= 1
不幸的是,这不适用于生成器,因为它需要知道序列的长度。
我不确定 pythonic 的定义,但您可以执行以下操作(按复杂性递增的顺序):
TLDR:采取 3
为了进行比较,我还列出了使用 Gnu time 的最大内存占用量 (M) 以及使用 jupyters 内置函数 %timeit -n 4 -r 4
的计算时间 (
T)。
参考尺寸
/usr/bin/time -v python3 -c 'list( int(1e6) * "abcdef" )'
结果为 61.4 MB。
正如之前所建议的:
reversed( list( enumerate(l) ) )
enumerate
返回一个生成器,并且生成器不可逆。
因此,
list
通过迭代整个生成器在内部创建一个新列表(直到抛出StopIteration
异常),并且reversed
以相反的顺序沿着该列表创建一个生成器。
这很简单,可能是“Pythonic”,但会产生大量的内存开销(在复制期间以及由于复制本身)。
M | T(每次循环的毫秒数 [4 次运行的平均值 ± 标准差,每次 4 次循环]) |
---|---|
673.6 MB | 1.04秒±24.9 |
正如我的评论中所写,您也可以使用
sorted( enumerate(), reverse=True )
这比上面的稍微清晰一些,并且作用几乎相同。
sorted
还在内部创建一个具有相关内存开销的副本,但另外还有一个排序操作。
由于对已排序列表进行排序相当快,因此运行时开销很小。
所以你在这里用可读性来换取运行时。
M | T(每次循环的毫秒数 [4 次运行的平均值 ± 标准差,每次 4 次循环]) |
---|---|
673.6 MB | 1.29秒±64毫秒 |
对于你所问的问题,据我所知,没有内置的生成器或链接生成器的方法。但你可以轻松地自己写一个,这就是我推荐的:
def enumerate_reversed(l):
for i in zip(range(len(l)-1, -1, -1), reversed(l)):
yield i
或者作为一句台词:
enumerate_reversed = lambda l: (x for x in zip(range(len(l)-1, -1, -1), reversed(l)))
reversed
、range
和 zip
都是返回发电机。
这样您就可以获得倒置的enumerate
,而无需创建任何中间副本。
M | T(每次循环的毫秒数 [4 次运行的平均值 ± 标准差,每次 4 次循环]) |
---|---|
61.7 MB | 1.26 秒 ± 17.3 毫秒 |
附录:
使用的命令:
方法 | 命令 |
---|---|
1 |
|
2 |
|
3 |
|