Python整个反转列表指定索引

8

我有一个列表,想要获得最后几个元素并以相反的顺序排列:

lst = [1,2,3,4]

我可以使用 lst[::-1] 来反转整个列表。但是我只想反转到某个特定的索引位置。我可以指定一个索引:

ind = 1
lst[:ind-1:-1]

并获得:

[4, 3, 2]

这个函数返回原始列表中从指定索引开始到列表末尾的元素,且返回结果是逆序。对于任何大于0的索引值都可使用。但如果索引值ind为0(表示返回整个列表的逆序),则会出现问题:

ind = 0
lst[:ind-1:-1]

返回:

[]

因为我的结束位置与我的起始位置相同(-1)。我期望/希望的输出应该是[4, 3, 2, 1]

我知道一个简单的解决方法就是加一个if语句来捕捉ind为0的情况,或者分两步走(先索引再反转),但感觉这应该可以用Python的索引系统来实现。我错了吗?


3
如果 "ind" 为0,你想要什么?你会得到你指定的内容。 - Prune
3
如果你必须通过切片来实现,可以在ind == 0时使用None,例如:lst[:None if ind==0 else ind-1:-1]。该语句的意思是,如果ind等于0,则切片从列表结尾一直切到开头;否则,从列表的第ind-1个元素开始倒序切片。 - AChampion
lst[:-5:-1],但感觉很难读。 - Josh Lee
2
@JoshLee 如果要泛化,您需要使用 lst[:ind-1-len(lst):-1]... - AChampion
@AChampion 啊!看起来我们有一个赢家!现在似乎很明显... - juanpa.arrivillaga
显示剩余3条评论
2个回答

5

None可以显式地表示“到末尾”(对于负步长,"end"是序列的开始):

lst[:ind - 1 if ind else None:-1]

虽然你说过你想避免两步法,但实际上这种方法更简单;除非你预计切片会很大,否则简化操作比可能遭受的微小性能损失更有价值:

lst[ind:][::-1]

值得一提的是,在微不足道的微基准测试中,假设每个ind值同样常见,一步法更快,但除非您的list很大,否则差异相当小。例如,对于您的四个元素list,使用ipython进行微基准测试:

>>> lst = [1, 2, 3, 4]
>>> %%timeit -r5 inds = range(len(lst))
... for ind in inds:
...     lst[:ind-1 if ind else None:-1]
...
1000000 loops, best of 5: 791 ns per loop

>>> %%timeit -r5 inds = range(len(lst))
... for ind in inds:
...     lst[ind:][::-1]
...
1000000 loops, best of 5: 1.1 µs per loop

虽然这种方法比较慢,但成本仅约为300纳秒。即使当lst长度为4000时,差异也只有每个循环18 vs 35.5毫秒;当然,时间将近翻倍,但如果这不是性能关键点(或列表通常较小),我认为这是可以接受的,因为它减轻了维护人员的负担,让他们更容易理解“从索引到结尾进行切片,然后反转”而不是更复杂的一步切片结构。


1
像@juanpa.arrigillage一样,我可能会利用reversed()而不是[::-1],因为它更易读,但这纯粹是个人风格的问题。 - AChampion
@AChampion:如果我只需要迭代一次并且不再使用它(for x in reversed(lst[ind:]):),我会使用 reversed。如果我确实需要结果作为一个 list,我更喜欢使用 [::-1];在 Python 中,这是 100% 的惯用法(至少我读起来比 reversed 快),而且速度更快(在相同的微基准测试中,使用 list(reversed(lst[ind:])) 的时间比使用 [::-1] 的两步解决方案长 50-150%)。它也更加友好;如果我在其他序列类型(例如 strtuple)上执行此切片,我将得到相同的类型,而不是 list - ShadowRanger

0

简单的技巧是使用

ind = 1

lst[:ind:-1] = 这将反转从指定索引开始的值列表。


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