Python:带间隙的切片的更短语法?

2022-03-26 00:00:00 python slice

问题描述

假设我想要Python列表中的第一个元素、第三个到第200个元素以及从第201个元素到最后一个元素的步长为3的元素。

一种方法是使用不同的索引和串联:

new_list = old_list[0:1] + old_list[3:201] + old_list[201::3]

有没有办法在old_list上只有一个索引就能做到这一点?我想要如下所示的内容(我知道这在语法上不起作用,因为列表索引不能是列表,而且不幸的是Pythondoesn't have slice literals;我只是在寻找接近的内容):

new_list = old_list[[0, 3:201, 201::3]]
我可以通过切换到NumPy数组来实现部分功能,但我更感兴趣的是如何对原生Python列表执行此操作。我还可以创建a slice maker或类似的东西,可能还会给出一个等价的切片对象来表示我所需的所有切片的组成。

但我正在寻找不需要创建新类来管理切片的东西。我只想将切片语法连接起来,并将其提供给我的列表,让列表理解这意味着要分别获取切片,并在最后连接它们各自的结果。


解决方案

切片生成器对象(例如,来自其他问题的SliceMakernp.s_)可以接受多个以逗号分隔的切片;它们作为slice或其他对象的tuple接收:

from numpy import s_
s_[0, 3:5, 6::3]
Out[1]: (0, slice(3, 5, None), slice(6, None, 3))

NumPy将其用于多维数组,但您可以将其用于切片串联:

def xslice(arr, slices):
    if isinstance(slices, tuple):
        return sum((arr[s] if isinstance(s, slice) else [arr[s]] for s in slices), [])
    elif isinstance(slices, slice):
        return arr[slices]
    else:
        return [arr[slices]]
xslice(list(range(10)), s_[0, 3:5, 6::3])
Out[1]: [0, 3, 4, 6, 9]
xslice(list(range(10)), s_[1])
Out[2]: [1]
xslice(list(range(10)), s_[:])
Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

相关文章