7

I often do sorts in Python using lambda expressions, and although it works fine, I find it not very readable, and was hoping there might be a better way. Here is a typical use case for me.

I have a list of numbers, e.g., x = [12, 101, 4, 56, ...]

I have a separate list of indices: y = range(len(x))

I want to sort y based on the values in x, and I do this:

y.sort(key=lambda a: x[a])

Is there a good way to do this without using lambda?

4
  • Any particular reason why a sorted list of the original values wouldn't suffice? x_sorted = sorted(x) Commented Aug 4, 2010 at 16:12
  • 1
    The OP wants the indexes of the elements in sorted order, not the elements themselves. Commented Aug 4, 2010 at 16:23
  • 1
    It is a shame that lambda is such a long and ugly keyword. This is pretty much the way to do it. Commented Aug 4, 2010 at 16:25
  • Looks very much similar than the stackoverflow.com/questions/3382352/… where I answered to give 'rank order list' solution, unfortunately with lambda. For me I prefer it though to the itemgetter solution. Commented Aug 4, 2010 at 20:23

4 Answers 4

13

You can use the __getitem__ method of the list x. This behaves the same as your lambda and will be much faster since it is implemented as a C function instead of a python function:

>>> x = [12, 101, 4, 56]
>>> y = range(len(x))
>>> sorted(y, key=x.__getitem__)
[2, 0, 3, 1]
Sign up to request clarification or add additional context in comments.

Comments

7

Not elegantly, but:

[a for (v, a) in sorted((x[a], a) for a in y)]

BTW, you can do this without creating a separate list of indices:

[i for (v, i) in sorted((v, i) for (i, v) in enumerate(x))]

Comments

5

I'm not sure if this is the kind of alternative you meant, but you could define the key function with a def:

def sort_key(value):
    return x[value]

y.sort(key = sort_key)

Personally, I think this is worse than the lambda as it moves the sort criteria away from the line of code doing the sort and it needlessly adds the sort_key function into your namespace.

Comments

0

I suppose if I wanted to create another function, I could do it something like this (not tested):

def sortUsingList(indices, values):
    return indices[:].sort(key=lambda a: values[a])

Though I think I prefer to use lambda instead to avoid having to create an extra function.

1 Comment

You are using lambda against ther request (though I would use it myself).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.