检查numpy数组是否已排序

时间:2017-10-29 19:45:04

标签: python numpy

我有一个numpy数组,我想检查它是否已排序。

>>> a = np.array([1,2,3,4,5])
array([1, 2, 3, 4, 5])

4 个答案:

答案 0 :(得分:20)

使用NumPy工具:

np.diff(a)>=0

但是numpy解决方案都是O(n)。

如果你想快速编写代码并在非排序数组上快速得出结论:

import numba
@numba.jit
def is_sorted(a):
    for i in range(a.size-1):
         if a[i+1] < a[i] :
               return False
    return True

在随机数组上是O(1)。

答案 1 :(得分:12)

np.all(a[:-1] <= a[1:])

示例:

is_sorted = lambda a: np.all(a[:-1] <= a[1:])

>>> a = np.array([1,2,3,4,9])
>>> is_sorted(a)
True

>>> a = np.array([1,2,3,4,3])
>>> is_sorted(a)
False

答案 2 :(得分:1)

低效但易于解决的解决方案:

(a == np.sort(a)).all()

答案 3 :(得分:0)

为完整性起见,下面找到O(log n)迭代解决方案。递归版本速度较慢,向量大小较大时会崩溃。但是,由于现代CPU优化,它仍然比使用np.all(a[:-1] <= a[1:])的本地numpy慢。 O(log n)更快的唯一情况是“平均”随机情况或“几乎”排序。如果您怀疑阵列已经完全排序,那么np.all会更快。

def is_sorted(a):
    idx = [(0, a.size - 1)]
    while idx:
        i, j = idx.pop(0) # Breadth-First will find almost-sorted in O(log N)
        if i >= j:
            continue
        elif a[i] > a[j]:
            return False
        elif i + 1 == j:
            continue
        else:
            mid = (i + j) >> 1 # Division by 2 with floor
            idx.append((i, mid))
            idx.append((mid, j))
    return True

is_sorted2 = lambda a: np.all(a[:-1] <= a[1:])

以下是结果:

# Already sorted array - np.all is super fast
sorted_array = np.sort(np.random.rand(1000000))

%timeit is_sorted(sorted_array)
659 ms ± 3.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit is_sorted2(sorted_array)
431 µs ± 35.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# Here I included the random in each command so we need to substract it's timing
%timeit np.random.rand(1000000)
6.08 ms ± 17.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit is_sorted(np.random.rand(1000000))
6.11 ms ± 58.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# Without random part, it took 6.11 ms - 6.08 ms = 30µs per loop

%timeit is_sorted2(np.random.rand(1000000))
6.83 ms ± 75.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# Without random part, it took 6.83 ms - 6.08 ms = 750µs per loop

Net,除非要运行超过1亿个元素数组,否则O(n)向量优化的代码要比O(log n)算法要好。