Fastest way to create strictly increasing lists in Python

后端 未结 5 2194
南方客
南方客 2021-02-07 09:03

I would like to find out what is the most efficient way to achieve the following in Python:

Suppose we have two lists a and b which are of equa

5条回答
  •  猫巷女王i
    2021-02-07 09:12

    unique with return_index uses argsort. With maximum.accumulate that isn't needed. So we can cannibalize unique and do:

    In [313]: a = [2,1,2,3,4,5,4,6,5,7,8,9,8,10,11]
    In [314]: arr = np.array(a)
    In [315]: aux = np.maximum.accumulate(arr)
    In [316]: flag = np.concatenate(([True], aux[1:] != aux[:-1])) # key unique step
    In [317]: idx = np.nonzero(flag)
    In [318]: idx
    Out[318]: (array([ 0,  3,  4,  5,  7,  9, 10, 11, 13, 14], dtype=int32),)
    In [319]: arr[idx]
    Out[319]: array([ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
    In [320]: np.array(b)[idx]
    Out[320]: array([ 1,  4,  5,  6,  8, 10, 11, 12, 14, 15])
    
    In [323]: np.unique(aux, return_index=True)[1]
    Out[323]: array([ 0,  3,  4,  5,  7,  9, 10, 11, 13, 14], dtype=int32)
    

    def foo(arr):
        aux=np.maximum.accumulate(arr)
        flag = np.concatenate(([True], aux[1:] != aux[:-1]))
        return np.nonzero(flag)[0]
    
    In [330]: timeit foo(arr)
    ....
    100000 loops, best of 3: 12.5 µs per loop
    In [331]: timeit np.unique(np.maximum.accumulate(arr), return_index=True)[1]
    ....
    10000 loops, best of 3: 21.5 µs per loop
    

    With (10000,) shape medium this sort-less unique has a substantial speed advantage:

    In [334]: timeit np.unique(np.maximum.accumulate(medium[0]), return_index=True)[1]
    1000 loops, best of 3: 351 µs per loop
    In [335]: timeit foo(medium[0])
    The slowest run took 4.14 times longer ....
    10000 loops, best of 3: 48.9 µs per loop
    

    [1]: Use np.source(np.unique) to see code, or ?? in IPython

提交回复
热议问题