假设我有一个数组/列表/字符串,例如arr=[0,1,2,3,...,97,98,99]
如何对其进行切片,使得输出是连续的块,步进一定量,例如:
out = [0,1,10,11,20,21..]
我已尝试out = arr[(0,1)::10]
的变体,但无济于事。我错过了一些非常简单的东西吗?
答案 0 :(得分:3)
首先:您对哪种类型感兴趣? numpy
数组允许扩展索引,而python内置函数(即list
,tuple
,str
等)则不允许。
如果您想要一个适用于任何一维序列的解决方案,那么只需使用:
from itertools import chain
result = list(chain.from_iterable(seq[i:i+step] for i in range(0, len(seq), step2))
在您的情况下,您希望step
2
和step2
为10
。
在任何情况下,对于通用序列,你必须为你想要选择的每个连续部分做一个切片,所以我认为你不能做得比这更好。
对于numpy
数组,您可以将数组reshape
转换为多维数组,以使连续部分全部位于行的开头并选择行的第一部分:
In [1]: import numpy as np
In [2]: seq = np.array(range(100))
In [3]: seq2 = seq.reshape((10, 10))
In [4]: seq2[:, :2]
Out[4]:
array([[ 0, 1],
[10, 11],
[20, 21],
[30, 31],
[40, 41],
[50, 51],
[60, 61],
[70, 71],
[80, 81],
[90, 91]])
In [5]: seq2[:, :2].reshape((2*10,))
Out[5]:
array([ 0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61, 70, 71, 80,
81, 90, 91])
(有很多方法可以重塑和展平结果;如果您有兴趣,请阅读numpy
文档。
但是请注意,如果切片重叠,这将失败,而第一个解决方案有效(重复一些元素,但这就是应该发生的事情)。
如果您不关心重叠切片(即切片永远不会重叠),那么您只需执行以下操作:
indices = frozenset(range(step))
result = [el for i, el in enumerate(seq) if i % step2 in indices]
这似乎比进行多次切片更有效,但我不会那么肯定,因为在这里你需要每个元素的索引操作而不是每个切片一个。特别是在CPython中,这可能不比第一个解决方案更有效,特别是如果step
很大的话。
从最后一个想法开始,你也可以做些什么来避免reshape
numpy数组:
indices = frozenset(range(step))
arr = np.array(i % step2 in indices for i in range(len(seq)))
result = seq[arr]
但是我想不出一种简单有效的方法来构建arr
索引数组,所以我怀疑它会提高性能。