如何检查一系列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速度运行。理想情况下,它也可以在第一次遇到错误结果时快速返回。
答案 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
和列数“小”时才会起作用。如果不是,计算中使用的整数将溢出,结果将是错误的。