Reputation: 191
When we want to sort a list of tuples, where each tuple is of length 3 (all increasing), we right the following code
ts = [(7, 14, 5), (3, 12, 9), (20, 22, 8), (20, 23, 24), (3, 12, 8), (4, 5, 7), (4, 5, 6), (4, 22, 17)]
ts.sort(key=lambda t: (t[0], t[1], t[2]))
By this I mean, that initially the elements at position zero are compared, lower the zero element in a tuple, the closer to the beginning it is. If two tuples have the same value at position zero, element with lower second element would be closer to the left. If two tuples have the same second element, third elements in a tuple are considered.
So the output of the above code is
Output: [(3, 12, 8), (3, 12, 9), (4, 5, 6), (4, 5, 7), (4, 22, 17), (7, 14, 5), (20, 22, 8), (20, 23, 24)]
But what if I want to reverse the ordering in some cases (not all), for example compare first elements, and if one tuple has smaller first element it is earlier in the sorted list. But if the first elements are the same, tuple with larger first element would be earlier in the list. And if the second elements in a tuple are the same, tuple with larger first element would be earlier in the list.
This could also be described as:
First consider first elements in a tuple, sort them in increasing order
If first elements in a tuple are the same, sort them in decreasing order
If second elements in a tuple are the same, sort them in decreasing order
So, the input I provided should be
Output: [(3, 12, 9), (3, 12, 8), (4, 22, 17), (4, 5, 7), (4, 5, 6), (7, 14, 5), (20, 23, 24), (20, 22, 8)]
I want to know, whether this could be done using a lambda function, or there has to be a separate method for the desired sorting.
We can also generalize this problem to a tuple of length n. What if we have a list of length n like
('increasing', 'decreasing', 'decreasing', ..., 'increasing', 'decreasing')
This would mean:
First consider first elements in a tuple, sort them in increasing order
If first elements in a tuple are the same, sort them in decreasing order
If second elements in a tuple are the same, sort them in decreasing order
If elements at position n - 2 in a tuple are the same, sort them in increasing order
if elements at position n - 1 in a tuple are the same, sort them in decreasing order
I would be happy, to see the solution to the problem about tuples of length 3, and discussion for the generalized problem, where the length of a tuple is n.
Upvotes: 3
Views: 2796
Reputation: 88236
You can change the signs in the tuples' values to get the expected behaviour:
ts.sort(key=lambda t: (t[0], -t[1], -t[2]))
print(ts)
# [(3, 12, 9), (3, 12, 8), (4, 22, 17), (4, 5, 7), (4, 5, 6), (7, 14, 5),
# (20, 23, 24), (20, 22, 8)]
For the general case, you can map the the increasing', 'decreasing'...
list to sings and zip
each tuple in the key
with the signs as:
l = ('increasing', 'decreasing', 'decreasing')
d = {'increasing':1, 'decreasing':-1}
signs = [d[i] for i in l]
ts.sort(key = lambda x: tuple(i*sign for sign,i in zip(signs, x)))
Which would yield the same as above:
print(ts)
# [(3, 12, 9), (3, 12, 8), (4, 22, 17), (4, 5, 7), (4, 5, 6), (7, 14, 5),
# (20, 23, 24), (20, 22, 8)]
Upvotes: 5