简体   繁体   中英

How to sort sublists based on an object within each sublist

I have a list of lists. Each list contains a description word, a word or sentence, and then an ordering list.

eg_list = [['sent', 'this is a sentence', [6, 1, 3]]
           ['word', 'abú', [5, 2, 9.5]]
           ['word', 'because', [5, 2, 11]]
           ['sent', 'this is not just one word', [6, 1, 1]]
           ['word', 'ol', [5, 2, 8]]
           ['word', 'magisteriums', [5, 1, 14]]]

I want to order the sublists based on the numbers in the ordering list at the end of each sublist. I need it to sort primarily by the first in the ordering list, then the middle number, then the last, so that the sorted result should look like this:

['word', 'magisteriums', [5, 1, 14]]
['word', 'ol', [5, 2, 8]]
['word', 'abú', [5, 2, 9.5]]
['word', 'because', [5, 2, 11]]
['sent', 'this is not just one word', [6, 1, 1]]
['sent', 'this is a sentence', [6, 1, 3]]

What kind of key can I put into the Python sorted() function to sort in this way?

Because you are comparing ordering lists with their elements from left to right, which is the ordinary order in which python does comparisons between lists, all that you need to do is provide a key function that extracts the ordering list itself -- this can be done with a lambda as shown below (although operator.itemgetter(2) would be an alternative). There is no need to explicitly reference elements within the ordering list.

To extract the ordering list, the example below uses lst[2] in the lambda (ie the 3rd element), but it could alternatively use lst[-1] (ie the last element).

from pprint import pprint  # pprint used for output display only

eg_list = [['sent', 'this is a sentence', [6, 1, 3]],
           ['word', 'abú', [5, 2, 9.5]],
           ['word', 'because', [5, 2, 11]],
           ['sent', 'this is not just one word', [6, 1, 1]],
           ['word', 'ol', [5, 2, 8]],
           ['word', 'magisteriums', [5, 1, 14]]]

pprint(sorted(eg_list, key=lambda lst:lst[2]))

This gives:

[['word', 'magisteriums', [5, 1, 14]],
 ['word', 'ol', [5, 2, 8]],
 ['word', 'abú', [5, 2, 9.5]],
 ['word', 'because', [5, 2, 11]],
 ['sent', 'this is not just one word', [6, 1, 1]],
 ['sent', 'this is a sentence', [6, 1, 3]]]

Update -- you also asked (in a comment) what you would do if you wanted to use the elements of the ordering list in a different order. What you would need to do in that case would be to write a key function that builds a new ordering list or tuple with the elements in the desired order. Although this could be squeezed into a one-liner, it is probably more convenient to write an explicit function for it. For example, to sort in order middle,left,right, you could use:

def get_key(lst):
    o_lst = lst[2]
    # let's return a tuple, although list would also work
    return (o_lst[1], o_lst[0], o_lst[2])  

You would then sort with key=get_key .

The equivalent one-liner would use:

key=lambda lst:(lst[2][1], lst[2][0], lst[2][2])

but the repetition of lst[2] makes this less preferable in my opinion.

In either case, you would get:

[['word', 'magisteriums', [5, 1, 14]],
 ['sent', 'this is not just one word', [6, 1, 1]],
 ['sent', 'this is a sentence', [6, 1, 3]],
 ['word', 'ol', [5, 2, 8]],
 ['word', 'abú', [5, 2, 9.5]],
 ['word', 'because', [5, 2, 11]]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM