Your desired behavior depends on Python doing a lexical sort of a list of lists. That is the sublists are compared as:
In [275]: [1,2]<[2,0]
Out[275]: True
np.sort only does a lexical sort with structured arrays and complex values.
In [288]: alist = [
...: [ [7, 1], [8, 0], [2, 0], [7, 1] ],
...: [ [5, 4], [1, 4], [6, 7], [8, 1] ],
...: [ [3, 2], [4, 5], [8, 6], [6, 2] ],
...: [ [6, 4], [1, 2], [5, 5], [7, 1] ]
...: ]
In [289]: arr = np.array(alist)
In [290]: arr
Out[290]:
array([[[7, 1],
[8, 0],
[2, 0],
[7, 1]],
[[5, 4],
[1, 4],
[6, 7],
[8, 1]],
[[3, 2],
[4, 5],
[8, 6],
[6, 2]],
[[6, 4],
[1, 2],
[5, 5],
[7, 1]]])
Let's try the complex route:
In [291]: x = np.dot(arr, [1,1j])
In [292]: x
Out[292]:
array([[7.+1.j, 8.+0.j, 2.+0.j, 7.+1.j],
[5.+4.j, 1.+4.j, 6.+7.j, 8.+1.j],
[3.+2.j, 4.+5.j, 8.+6.j, 6.+2.j],
[6.+4.j, 1.+2.j, 5.+5.j, 7.+1.j]])
In [293]: np.min(x)
Out[293]: (1+2j)
In [294]: np.argmin(x)
Out[294]: 13
In [295]: np.unravel_index(13, x.shape)
Out[295]: (3, 1)
Some time tests:
In [302]: timeit min(nested2 for nested1 in alist for nested2 in nested1)
2.24 µs ± 19.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [303]: timeit min(arr.reshape(-1,2).tolist())
2.53 µs ± 13.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [304]: timeit np.min(arr.dot([1,1j]))
19.5 µs ± 46.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
The complex route might be faster when the array is much bigger, but with this sample it is inferior.
===
The structured array approach:
In [320]: import numpy.lib.recfunctions as rf
In [321]: rf.unstructured_to_structured(arr, names=['x','y'])
Out[321]:
array([[(7, 1), (8, 0), (2, 0), (7, 1)],
[(5, 4), (1, 4), (6, 7), (8, 1)],
[(3, 2), (4, 5), (8, 6), (6, 2)],
[(6, 4), (1, 2), (5, 5), (7, 1)]],
dtype=[('x', '<i8'), ('y', '<i8')])
In [322]: np.argsort(rf.unstructured_to_structured(arr, names=['x','y']).ravel())
Out[322]: array([13, 5, 2, 8, 9, 4, 14, 11, 12, 6, 0, 3, 15, 1, 7, 10])
In [323]: timeit np.argsort(rf.unstructured_to_structured(arr, names=['x','y']).ravel())
41.3 µs ± 192 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
minis using a Pythonsortwhich for a list of lists of integers is 'lexical'. It appears that you are starting with a numpy array, in which case your last expression could be shorted tomin(array.reshape(-1,2).tolist()). That is, replace the nesting with an array reshape..tolist()costs on average around 5.4 seconds for each iteration. Everything else runs in under 100ms. So I was hoping to pass on the heavy lifting to numpy...