Python: Sort list of lists by not one, but two criteria

Question:

I have a Python sorting problem which is similar to other problems I found on stackoverflow, but not quite the same. Let me show you, maybe someone may help:

Assume that we have a list of lists which may look like this:

p = [[6, 'k'], [5, 'l'], [2, 'p'], [2, 'd'], [5, 'k']]

I want to sort this by two (!) criteria. Sorting it by one criterion is rather easy and straightforward. Let’s assume I want to first sort it by the first item of each list. I could implement this as such:

sorted_p = sorted(p, key=lambda x:int(x[0]))

So far so good. I would get the following sorted_p:

[[2,'p'], [2, 'd'], [5, 'l'], [5, 'k'], [6, 'k']]

Now the real trouble starts: I want that in every case where there are multiple occurrences of the first item (e.g. we have two tuples starting with 2 and two tuples starting with 5) that these tuples are then sorted by the second item of the tuple. So what I would like to get as a result would be

[[2,'d'], [2, 'p'], [5, 'k'], [5, 'l'], [6, 'k']]

Has anyone an idea how I can do that?

Thanks for every hint!

Asked By: TimoSan

||

Answers:

Python automatically sorts by more than 1 criteria if you pass it a tuple. In your case it would be:

p = [[6, 'k'], [5, 'l'], [2, 'p'], [2, 'd'], [5, 'k']]
sorted_p = sorted(p, key=lambda x:(int(x[0]),x[1]))
Answered By: Advay168

The accepted answer is great. Just adding another answer without using the built-in sort in case of customizations it can be extended.

def custom_bubble_sort(arr):
    for i in range(len(arr)-1):
        for j in range(len(arr)-i-1):
            if arr[j][0] > arr[j+1][0]:
                temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
            elif arr[j][0] == arr[j+1][0] and ord(arr[j][1]) > ord(arr[j+1][1]):
                    temp = arr[j]
                    arr[j] = arr[j+1]
                    arr[j+1] = temp
    return arr

print(custom_bubble_sort([[6, 'k'], [5, 'l'], [2, 'p'], [2, 'd'], [5, 'k']]))
Answered By: coldy

I think this version using operator.itemgetter reads better than the lambda version:

import operator
p = [[6, 'k'], [5, 'l'], [2, 'p'], [2, 'd'], [5, 'k']]
sorted_p = sorted(p, key=operator.itemgetter(0, 1))
Answered By: htaccess
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.