vnikonov_63
vnikonov_63

Reputation: 191

Sorting a list of tuples in different order based on the values of a tuple

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:

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:

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

Answers (1)

yatu
yatu

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

Related Questions