Explain Codes LogoExplain Codes Logo

How to get indices of a sorted array in Python

python
list-comprehensions
numpy
performance-analysis
Alex KataevbyAlex Kataev·Feb 18, 2025
TLDR

Quickly obtain sorted array indices in Python using numpy.argsort():

import numpy as np array = [3, 1, 2] indices = np.argsort(array) print(indices) # Produces [1, 2, 0] - Don't mix them up with your locker combination!

np.argsort() yields indices to arrange an array in ascending order. In this case, it turns [3, 1, 2] into [1, 2, 3], as indicated by the indices [1, 2, 0].

No NumPy? No problem!

Python's built-in functions got you covered when NumPy isn't available. For instance, sorted(enumerate(list), key=lambda x: x[1]) can do the job, packaging index-value pairs, sorted by value:

array = [5, 1, 3] # This function also doubles as an excellent party trick! sorted_indices = [i for (i, _) in sorted(enumerate(array), key=lambda x: x[1])] print(sorted_indices) # Gives you: [1, 2, 0]

If enumerate list comprehension doesn't tickle your fancy, sorted(range(len(list)), key=list.__getitem__) offers a simpler mechanism, connecting you straight to the indices:

array = [5, 1, 3] # A simple mechanism for simple needs, one might say! sorted_indices = sorted(range(len(array)), key=array.__getitem__) print(sorted_indices) # Fetches you: [1, 2, 0]

Advanced sorting techniques that break ties beautifully

Sometimes, duels aren't your thing. To solve fights AKA ties, we can maintain the original order in the sorted array through stable sorting. Here's how to retrieve the indices for a stable sort:

array = [3, 1, 2, 1] # For those who don't favor duels, this gives you a truce (or a stable sort!) sorted_indices = sorted(range(len(array)), key=lambda i: (array[i], i)) print(sorted_indices) # Resolves the tie between two '1's, resulting in: [1, 3, 2, 0]

Also, for tackling complex comparisons or handling custom objects, key parameters can be combined with bespoke functions.

Spicing up the order

For those who enjoy chaos - Descending order

Let's shake things up a bit! To sort in a descending order, simply append a minus sign (-) to the sort key:

array = [3, 1, 2] # Bigger is better, right? Reverse your array here and now! sorted_indices = np.argsort([-a for a in array]) print(sorted_indices) # [0, 2, 1] defying gravity!

Dealing with multi-dimensional arrays

For 2D arrays or matrices, specify the axis to control whether you want the sort to occur along rows or columns:

matrix = np.array([[3, 2], [1, 0]]) # Rows or columns, why not both? row_sort_indices = np.argsort(matrix, axis=1) column_sort_indices = np.argsort(matrix, axis=0) print(row_sort_indices) # [[1, 0], [1, 0]] - Not quite tic-tac-toe, but close enough! print(column_sort_indices) # [[1, 1], [0, 0]] - And the award for consistency goes to...

Working with complex data

For complex comparisons or custom objects, the attrgetter or itemgetter from the operator module provide efficient sorting:

from operator import itemgetter pairs = [(2, 'apple'), (1, 'banana'), (2, 'cherry')] # Cherries, apples and bananas get into a fight; who exits first? Let's find out! sorted_indices = sorted(range(len(pairs)), key=itemgetter(0)) print(sorted_indices) # The award for exiting first goes to Banana! Result: [1, 0, 2]

Efficiency first

Perks of picking perfplot for performance analysis

A tool like perfplot can confirm how different methods perform. Through its exciting graphs, you can analyze how np.argsort() fares against other sorting techniques.

Ponderings for large datasets

For larger datasets, algorithmic complexity comes into play. While argsort from NumPy is fairly optimized, Python's native methods with list comprehensions might want to take the back seat for these!