什么是将数组切割成阶梯连续块的pythonic方法?

时间:2014-12-03 09:51:42

标签: python arrays numpy

假设我有一个数组/列表/字符串,例如arr=[0,1,2,3,...,97,98,99]

如何对其进行切片,使得输出是连续的块,步进一定量,例如:

out = [0,1,10,11,20,21..]

我已尝试out = arr[(0,1)::10]的变体,但无济于事。我错过了一些非常简单的东西吗?

1 个答案:

答案 0 :(得分:3)

首先:您对哪种类型感兴趣? numpy数组允许扩展索引,而python内置函数(即listtuplestr等)则不允许。

如果您想要一个适用于任何一维序列的解决方案,那么只需使用:

from itertools import chain

result = list(chain.from_iterable(seq[i:i+step] for i in range(0, len(seq), step2))

在您的情况下,您希望step 2step210

在任何情况下,对于通用序列,你必须为你想要选择的每个连续部分做一个切片,所以我认为你不能做得比这更好。

对于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索引数组,所以我怀疑它会提高性能。