关于python:包含第一个元素的反向数组切片

Reversed array slice including the first element

本问题已经有最佳答案,请猛点这里访问。

假设我有:

1
>>> a = [1, 2, 3, 4]

我想做个反转切片。比如说,我想要给定start_idx = 1stop_idx = 0的第1和第0个元素:

1
[2, 1]

使用切片符号:

1
a[x:y:z]

对于使用start_idxstop_idxxyz,我应该使用什么值?

我试过了:

1
2
3
4
>>> a[start_idx:stop_idx:-1]
[2]
>>> a[start_idx:stop_idx-1:-1]
[]

区别:

这个问题是关于一个带有负步骤的切片,其中开始和结束索引元素都应该包括在内(就像数学中的闭合间隔),并且切片结束索引是动态计算的。

了解python的切片表示法是关于符号的一般性问题:在a[x:y:z]中,xyz的含义是什么?它没有提到逆转的情况。

这个问题不同于其他标记的重复项,因为它处理的是反向切片开始和结束索引要么由变量计算,要么由变量给出,而不是硬编码的一般情况。


如果希望反向间隔以索引0结尾,则切片时可以省略第二个索引。

1
2
a = [1, 2, 3, 4]
a[1::-1] # [2, 1]

通常,当最终索引为零时,您希望用None替换它,否则您希望将其递减。

由于索引算法的原因,我们必须分别处理这些情况,以与通常的切片行为保持一致。这可以用三元表达式巧妙地完成。

1
2
3
4
def reversed_interval(lst, i=None, j=None):
    return lst[j:i - 1 if i else None:-1]

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

以下是两种通用解决方案:

  • 向前切片,然后反转:

    1
    2
    >>> a[stop_idx:start_idx+1][::-1]
    [2, 1]
  • 基于此答案,在第一个元素(加上停止偏移量)之前使用负的步骤并停止1个元素:

    1
    2
    >>> a[start_idx:stop_idx-len(a)-1:-1]
    [2, 1]
  • 比较执行时间,第一个版本更快:

    1
    2
    3
    4
    >>> timeit.timeit('foo[stop_idx:start_idx+1][::-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
    1.7157553750148509
    >>> timeit.timeit('foo[start_idx:stop_idx-len(foo)-1:-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
    1.9317215870250948