Python仅枚举反向索引
Posted
技术标签:
【中文标题】Python仅枚举反向索引【英文标题】:Python enumerate reverse index only 【发布时间】:2016-12-08 21:03:23 【问题描述】:我正在尝试反转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)))))
我只是想知道是否有更简洁的方法可以做到这一点?
【问题讨论】:
【参考方案1】:使用 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
获取生成器【参考方案2】:
我不知道这个解决方案是否更适合你,但至少它更短:
>>> [(4 - x, x) for x in range(5)]
[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]
【讨论】:
【参考方案3】:只需获取列表的长度并从中减去索引...
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()
不可能这样做,因为它适用于通用迭代器。例如,您可以向它传递无限迭代器,甚至没有“反向索引”。
【讨论】:
【参考方案4】:假设您的列表不长并且您不会遇到性能错误,您可以使用list(enumerate(range(5)[::-1]))[::-1]
。
测试:
>>> list(enumerate(range(5)[::-1]))[::-1]
[(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]
【讨论】:
据我所知,我提供了最简洁的方法。不过,这个问题有点意思。 他希望索引被反转,而不是列表 糟糕!正确的。固定。 这也是我会做的。我个人什至不关心最后的反转......【参考方案5】:其实我使用的逻辑和@RemcoGerlich 一样,但是我直接使用list comprehension
,这使得代码现在变成了1-liner:
def generatelist(x):
return [(x-1-i,n) for i,n in enumerate(range(x))]
关于选择generator
或list comprehension
的困境,here是建议的方式:
基本上,如果您所做的只是迭代一次,请使用生成器表达式。如果您想存储和使用生成的结果,那么最好使用列表推导式。
【讨论】:
【参考方案6】:如果你打算多次重复使用它,你可以制作自己的生成器:
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))
【讨论】:
【参考方案7】:Python 2
import itertools
def reversed_enumerate(seq):
return itertools.izip(reversed(range(len(seq))), reversed(seq))
Python 3
用zip
替换itertools.izip
:)
【讨论】:
【参考方案8】:只要在使用 i 的地方使用 len(lst)-i
。或:
[(len(range(5)) - x, x) for x in range(5)]
【讨论】:
-(i+1)
或 -1-i
。【参考方案9】:
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)
【讨论】:
请描述您进行了哪些更改以及更改的原因,以帮助其他人识别问题并理解此答案【参考方案10】:我们可以使用 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
$
【讨论】:
以上是关于Python仅枚举反向索引的主要内容,如果未能解决你的问题,请参考以下文章