+ 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
7 ответов
+ 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)))
+ 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 👍
+ 7
The argument should be a function that is applied on the list's elements.
Try:
sort(lst, key=len)
+ 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))
+ 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
+ 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
+ 2
look into itemgetter
https://docs.python.org/3/library/operator.html#operator.itemgetter