+ 8

How to sort a list of lists by length?

Suppose I have a list of lists in Python and I would like to sort them primarily by the length (of the list elements) and if the lengths are equal, secondarily sort them lexicographically. From lst=[ [0], [0,3], [1], [0,1]] I would like to get [[0], [1], [0,1], [0,3]] What should I pass to the key argument of sort function? sort(lst, key=???) If I could write a comparator, not a key function, it would be a lot easier. Or should I use the cmp_to_key function from functools? Thanks for help

17th Feb 2019, 11:28 AM
michal
7 Respuestas
+ 8
If you want to use more than one sorting criterion, you can store them in a tuple: from random import randint l = [[randint(1, 5) for i in range(randint(1, 5))] for j in range(randint(5, 10))] print(l) # example output: [[2, 5, 2, 1, 3], [1, 5], [2], [4, 5], [3, 1, 3, 4, 1]] def sort_list(l): return (len(l), l) # sort by len() first, then by item (=lexicographically) for items with same len() print(sorted(l, key=sort_list)) # [[2], [1, 5], [4, 5], [2, 5, 2, 1, 3], [3, 1, 3, 4, 1]] This is equivalent to: print(sorted(l, key=lambda x:(len(x), x)))
17th Feb 2019, 12:03 PM
Anna
Anna - avatar
+ 8
michal I'd have to check on that. I think it sorts lexicographically by default so after taking into account that it is already sorted by lenght first, the other key is already the lexi one. Still, of course it pays off to be explicit when coding so that you are assured no random effect will surprise you 👍
17th Feb 2019, 2:04 PM
Kuba Siekierzyński
Kuba Siekierzyński - avatar
+ 7
The argument should be a function that is applied on the list's elements. Try: sort(lst, key=len)
17th Feb 2019, 12:00 PM
Kuba Siekierzyński
Kuba Siekierzyński - avatar
+ 5
In addition to Kuba's suggestion, if you want to sort by mutliple attributes simultaneously, you can use a lambda function to generate a tuple as key for each item. then the elements are sorted based on the tuple -- if there is equality in the first key then the next one is used. lst.sort(key=lambda x: (len(x), x))
17th Feb 2019, 12:02 PM
Tibor Santa
Tibor Santa - avatar
+ 5
Kuba Siekierzyński This sorts only by the length, not lexicographically in case of same length. The best solution appears to be using tuples
17th Feb 2019, 12:20 PM
michal
+ 3
I really suspect that the sort method could't be very capable for more than one sort. But I would suggest that you first do: list.sort(key=len) Then you split the list by it's innerlist lengths: sublists = [[]] counter = 0 for i in list: if len(i) == counter: sublists[counter].append(i) else: counter += 1 sublists.append([i]) Then you do a sort with key=specialsum, a function defined with def for each item in sublists. for i in sublists: i.sort(key=specialsum) Then you parse it to a new list: newlist = [] for i in sublists: newlist.extend(i) Sample: https://code.sololearn.com/cmtnSBAc9Kmf/?ref=app
17th Feb 2019, 12:02 PM
Seb TheS
Seb TheS - avatar
+ 2
look into itemgetter https://docs.python.org/3/library/operator.html#operator.itemgetter
17th Feb 2019, 11:58 AM
peter
peter - avatar