Python Numpy检测列表中的递增范围

Python Numpy检测列表中的递增范围,python,numpy,math,Python,Numpy,Math,我有一个列表,看起来像这样(实际上它更大) 1,2,3,4,6,7,9,12,14,15,16 我想自动检测没有间隙的范围,这样我就可以得到这样的元组数组 (1,4)、(6,7)、(9,9)、(12,12)、(14,16) 在numpy有什么有效的方法可以做到这一点?方法#1 我们将使用循环切片的方法,但在预处理部分使用NumPy进行所有计算以获得性能。对数组进行切片只是对视图进行操作,因此应该非常有效。这里有一个实现这些目标的方法- def start_stop_with_seq(a):

我有一个列表,看起来像这样(实际上它更大)

1,2,3,4,6,7,9,12,14,15,16

我想自动检测没有间隙的范围,这样我就可以得到这样的元组数组

(1,4)、(6,7)、(9,9)、(12,12)、(14,16)

在numpy有什么有效的方法可以做到这一点?

方法#1

我们将使用循环切片的方法,但在预处理部分使用NumPy进行所有计算以获得性能。对数组进行切片只是对视图进行操作,因此应该非常有效。这里有一个实现这些目标的方法-

def start_stop_with_seq(a):
    m = np.r_[True,np.diff(a)!=1,True]
    idx = np.flatnonzero(m)
    return [(a[i],a[j-1]) for (i,j) in zip(idx[:-1],idx[1:])]
样本运行-

In [115]: a
Out[115]: [1, 2, 3, 4, 6, 7, 9, 12, 14, 15, 16]

In [116]: start_stop_with_seq(a)
Out[116]: [(1, 4), (6, 7), (9, 9), (12, 12), (14, 16)]
方法#2

我们可以将向量化解决方案的输入列表索引到一个数组中,并使用索引替换上一个切片部分-

def start_stop_with_seq_v2(a):
    a = np.asarray(a)
    m = np.r_[True,np.diff(a)!=1,True]
    return np.c_[a[m[:-1]], a[m[1:]]]
给定样本的输出-

In [163]: start_stop_with_seq_v2(a)
Out[163]: 
array([[ 1,  4],
       [ 6,  7],
       [ 9,  9],
       [12, 12],
       [14, 16]])
如果输出有许多间隔,这种方法是有意义的

标杆管理 在一个更大(类似于给定样本)的数据集上进行测试-

In [217]: np.random.seed(0)

In [218]: a = np.unique(np.random.randint(0,100000,(200000))).tolist()

In [219]: %timeit intspan(a).ranges()
29.9 ms ± 343 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [220]: %timeit start_stop_with_seq(a)
14.3 ms ± 84.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [221]: %timeit start_stop_with_seq_v2(a)
6.78 ms ± 57.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

不是在numpy中,但是这里有一种方法,使用它比intspan有什么优势吗?@user2741831不确定。没有与intspan合作过。基准测试并让我知道?我看看是否能做到。但如果它足够好的话,我可能会坚持下去it@user2741831根据大众需求,增加了基准测试。满足您的需要?@user2741831如果您的问题已得到回答或有帮助,您可以接受并投票。更多信息-