5

While working on a problem from Google Python class, I formulated following result by using 2-3 examples from Stack overflow-

def sort_last(tuples):
    return [b for a,b in sorted((tup[1], tup) for tup in tuples)]

print sort_last([(1, 3), (3, 2), (2, 1)])

I learned List comprehension yesterday, so know a little about list comprehension but I am confused how this solution is working overall. Please help me to understand this (2nd line in function).

2

4 Answers 4

6

That pattern is called decorate-sort-undecorate.

  1. You turn each (1, 3) into (3, (1, 3)), wrapping each tuple in a new tuple, with the item you want to sort by first.
  2. You sort, with the outer tuple ensuring that the second item in the original tuple is sorted on first.
  3. You go back from (3, (1, 3)) to (1, 3) while maintaining the order of the list.

In Python, explicitly decorating is almost always unnecessary. Instead, use the key argument of sorted:

sorted(list_of_tuples, key=lambda tup: tup[1]) # or key=operator.itemgetter(1)

Or, if you want to sort on the reversed version of the tuple, no matter its length:

sorted(list_of_tuples, key=lambda tup: tup[::-1]) 
                              # or key=operator.itemgetter(slice(None, None, -1))
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot, it is clear now, can you please tell me something about lambda (I know I can find about it on stack overflow, but want to know about your use of lambda here)
@Varun lambda just lets you declare a function inside an expression. It's the same as def first_item(tup): return tup[1] outside the function call, then key = first_item in the function call. See Lambda Forms in the Python Tutorial.
"That pattern is called decorate-sort-undecorate" .. never knew it has a name
3

Lets break it down:

In : [(tup[1],tup) for tup in tuples]

Out: [(3, (1, 3)), (2, (3, 2)), (1, (2, 1))]

So we just created new tuple where its first value is the last value of inner tuple - this way it is sorted by the 2nd value of each tuple in 'tuples'.

Now we sort the returned list:

In: sorted([(3, (1, 3)), (2, (3, 2)), (1, (2, 1))])

Out: [(1, (2, 1)), (2, (3, 2)), (3, (1, 3))]

So we now have our list sorted by its 2nd value of each tuple. All that is remain is to extract the original tuple, and this is done by taking only b from the for loop.

The list comprehension iterates the given list (sorted([...] in this case) and returns the extracted values by order.

1 Comment

Thanks a lot, nicely explained.
2

Your example works by creating a new list with the element at index 1 followed by the original tuple for each tuple in the list. Eg. (3,(1,3)) for the first element. The sorted function sorts by each element starting from index 0 so the list is sorted by the second item. The function then goes through each item in the new list, and returns the orignal tuples.

Another way of doing this is by using the key parameter in the sorted function which sorts based on the value of the key. In this case you want the key to be the item in each tuple at index 1.

>>> from operator import itemgetter
>>> sorted([(1, 3), (3, 2), (2, 1)],key=itemgetter(1))

2 Comments

It does not reverse each tuple in the list. It wraps each tuple in another tuple.
Oh right i missed that, i thought it was tup[1],tup[0] but now that i looked back on it i see i have misread it, i will edit my answer.
0

Pls refer to the accepted answer.. + here is an example for better visualization,

key is a function that will be called to transform the collection's items for comparison.. like compareTo method in Java.

The parameter passed to key must be something that is callable. Here, the use of lambda creates an anonymous function (which is a callable).
The syntax of lambda is the word lambda followed by a iterable name then a single block of code.

Below example, we are sorting a list of tuple that holds the info abt time of certain event and actor name.

We are sorting this list by time of event occurrence - which is the 0th element of a tuple.

Shout out for the Ready Player One fans! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

Note - s.sort([cmp[, key[, reverse]]]) sorts the items of s in place

Comments

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.