检查numpy数组是否按字典顺序排序

时间:2017-05-01 14:49:02

标签: python numpy

如何检查一系列numpy数组是否按字典顺序排序?

>>> x = np.asarray([0, 0, 1, 1])
>>> y = np.asarray([0, 1, 0, 2])
>>> is_lex_sorted([x, y])
True

>>> x = np.asarray([100, 0, 1, 1])
>>> y = np.asarray([0, 1, 0, 2])
>>> is_lex_sorted([x, y])
False

理想情况下,此检查将以线性时间运行并以NumPy速度运行。理想情况下,它也可以在第一次遇到错误结果时快速返回。

2 个答案:

答案 0 :(得分:2)

使用纯NumPy函数的is_lexsorted实现几乎肯定需要在一个或多个数组上进行多次传递(因为NumPy函数被设计为一次性在整个数组上运行)。

这意味着如果速度是主要考虑因素,在numba或Cython中编写函数可能是更好的选择。

已经在pandas中实现了一个这样的Cython函数is_lexsorted。这具有您指定的短路行为,其运行时间与数组的数量和长度呈线性关系。

>>> from pandas.algos import is_lexsorted 
>>> x = np.asarray([0, 0, 1, 1])
>>> y = np.asarray([0, 1, 0, 2])
>>> is_lexsorted([x, y])
True

(对于pandas 0.20.0+使用from pandas.lib import is_lexsorted。)

在pandas中,它用于检查MultiIndexes的级别是否已排序。但是,请注意,它不在公共API中,因此将来可能会发生变化。

答案 1 :(得分:2)

如果n(数组中的最大整数)和列数不是太大,您可以以保留字典顺序的方式将每一行转换为整数:

def is_lex_sorted(a):
    n = a.max() + 1
    v = (a*(n**np.arange(a.shape[1]-1, -1, -1))).sum(axis=1)
    return np.all(v[:-1] <= v[1:])

例如,

In [230]: x
Out[230]: 
array([[0, 0, 1],
       [0, 1, 2],
       [1, 0, 4],
       [1, 2, 1]])

In [231]: is_lex_sorted(x)
Out[231]: True

In [232]: y
Out[232]: 
array([[  0,   0,   1,  13],
       [  0,   1,   2,  30],
       [100,   0,   4,  10],
       [  1,  20,   1,  80]])

In [233]: is_lex_sorted(y)
Out[233]: False

两个问题:

  • 仅当n和列数“小”时才会起作用。如果不是,计算中使用的整数将溢出,结果将是错误的。
  • 它不会提前停止。