Python枚举反向索引

25

我试图反转由 enumerate 给出的索引,同时保留正在枚举的列表的原始顺序。

假设我有以下内容:

>> range(5)
[0, 1, 2, 3, 4]

如果我列举一下,会得到以下内容:

>> list(enumerate(range(5)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

然而我想要反转由enumerate提供的索引,以便我得到:

[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]

到目前为止,我有以下的代码:

reversed(list(enumerate(reversed(range(5)))))
我在想是否有更简洁的方法来做这件事?
10个回答

24

使用反向范围与zip一起使用怎么样?

>>> zip(range(9, -1, -1), range(10))
[(9, 0), (8, 1), (7, 2), (6, 3), (5, 4), (4, 5), (3, 6), (2, 7), (1, 8), (0, 9)]


>>> def reversedEnumerate(l):
        return zip(range(len(l)-1, -1, -1), l)
>>> reversedEnumerate(range(10))
[(9, 0), (8, 1), (7, 2), (6, 3), (5, 4), (4, 5), (3, 6), (2, 7), (1, 8), (0, 9)]

正如 @julienSpronk 建议的那样,使用 izip 来获得一个生成器,还可以使用 xrange:

import itertools
>>> import itertools
>>> def reversedEnumerate(l):
...     return itertools.izip(xrange(len(l)-1, -1, -1), l)
...     
>>> reversedEnumerate(range(10))
<itertools.izip object at 0x03749760>
>>> for i in reversedEnumerate(range(10)):
...     print i
...     
(9, 0)
(8, 1)
(7, 2)
(6, 3)
(5, 4)
(4, 5)
(3, 6)
(2, 7)
(1, 8)
(0, 9)

或者使用itertools.izip来获取一个生成器。 - Julien Spronck

7

只需获取列表的长度并从中减去索引...

L = range(5)

for i, n in L:
    my_i = len(L) -1 - i
    ...

如果你真的需要一个生成器:

def reverse_enumerate(L):
   # Only works on things that have a len()
   l = len(L)
   for i, n in enumerate(L):
       yield l-i-1, n

enumerate() 无法做到这一点,因为它使用的是通用迭代器。例如,您可以传递无限迭代器给它,甚至没有“反向索引”。


7

我不知道这个解决方案是否更适合您,但至少它更短:

>>> [(4 - x, x) for x in range(5)]
[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]

5
假设你的列表不是很长,也不会出现性能错误,可以使用list(enumerate(range(5)[::-1]))[::-1]
测试: >>> list(enumerate(range(5)[::-1]))[::-1] [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]

我提供了我理解的最简洁的方法来完成这个问题。然而,这个问题有点主观。 - Emil
他想要索引被反转,而不是列表。 - Netwave
哎呀!对了,修好了。 - Emil
这也是我会做的。我个人甚至不会关心最后一个反转... - zwep

4

实际上,我使用了与@RemcoGerlich相同的逻辑,但我直接使用列表推导式,这使代码现在成为一行:

def generatelist(x):
    return [(x-1-i,n) for i,n in enumerate(range(x))]

关于选择使用 generator 还是 list comprehension 的困境,这里 给出了建议:

基本上,如果你只需要迭代一次,那么使用生成器表达式。如果你想要存储和使用生成的结果,那么最好使用列表推导。


2
如果您需要多次重复使用它,您可以制作自己的生成器:
def reverse_enum(lst):
    for j, item in enumerate(lst):
        yield len(lst)-1-j, item

print list(reverse_enum(range(5)))
# [(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]

或者

def reverse_enum(lst):
    return ((len(lst)-1-j, item) for j, item in enumerate(lst))

2

Python 2

import itertools

def reversed_enumerate(seq):
    return itertools.izip(reversed(range(len(seq))), reversed(seq))

Python 3

itertools.izip替换为zip :)


1
values = 'abcde'

for i, value in zip(reversed(range(len(values))), values):
    print(i, value)

解释:

values = 'abcde'

values_len = len(values) # 5
indexes = range(values_len) # [0, 1, 2, 3, 4]
reversed_indexes = reversed(indexes) # [4, 3, 2, 1, 0]

# combine reversed indexes and values
reversed_enumerator = zip(reversed_indexes, values)

for i, value in reversed_enumerator:
    print(i, value)

请描述您更改了什么以及为什么更改,以帮助其他人识别问题并理解此答案。 - FZs

1

我们可以使用enumerate和len:

$ cat enumerate.py 


arr = ['stone', 'cold', 'steve', 'austin']
for i, val in enumerate(arr):
    print ("enu {} val {}".format(i, val))
for i, val in enumerate(arr):
    print ("enu {} val {}".format(len(arr) - i - 1, val))
$  python enumerate.py 
enu 0 val stone
enu 1 val cold
enu 2 val steve
enu 3 val austin
enu 3 val stone
enu 2 val cold
enu 1 val steve
enu 0 val austin
$  

1

只需在使用i的所有地方使用len(lst)-i。或者:

[(len(range(5)) - x, x) for x in range(5)]

-(i+1) 或者 -1-i - tzot

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