In Python you can for example sort tuples sorted([(2,2),(1,2),(2,1),(1,1)])
and get [(1, 1), (1, 2), (2, 1), (2, 2)]
.
You can also use custom k
from collections import Iterable
def custom_key(item):
if isinstance(item, Iterable) and not isinstance(item, basestring):
return [medals_map.get(ele, ele) for ele in item]
return medals_map.get(item, item)
Output:
In [2]: assert sorted(['Silver', 'Bronze', 'Gold'], key=custom_key) == ['Gold', 'Silver', 'Bronze']
In [3]: assert sorted([['Silver', 2], ['Silver', 1], ['Gold', 1]], key=custom_key) == [['Gold', 1], ['Silver', 1], ['Silver', 2]]
In [4]: assert sorted([(2, 'Gold'), (2, 'Bronze'), (1, 'Gold')], key=custom_key) == [(1, 'Gold'), (2, 'Gold'), (2, 'Bronze')]
In [5]: assert sorted([('Silver', 'Bronze'), ('Gold', 'Bronze'), ('Silver', 'Gold')], key=custom_key) == [('Gold', 'Bronze'), ('Silver', 'Gold'), ('Silver', 'Bronze')]
You don't need a extra function. You can also do it:
medals_map = {'Gold': 1, 'Silver': 2, 'Bronze': 3 }
List = [('Bronze', 1), ('Gold', 1), ('Gold', 2)]
new_list = sorted(List, key=lambda word: (medals_map[word[0]], word[1]))
print new_list
Output:
[('Gold', 1), ('Gold', 2), ('Bronze', 1)]
The key function can return a tuple:
medals_map = {'Gold': 1, 'Silver': 2, 'Bronze': 3 }
def custom_key(item):
if isinstance(item, basestring):
try:
return medals_map[item]
except KeyError:
pass
return item
print sorted([('Gold', 2), ('Bronze', 1), ('Gold', 1)], key=lambda x: (custom_key(x[0]), x[1]))
Prints [('Gold', 1), ('Gold', 2), ('Bronze', 1)]
. Essentially this makes the sorting behave the same as your first example, i.e. sorted([(1, 2), (3, 1), (1, 1)])
.
Edit: you can also make a custom key that returns a tuple, which may be prettier.
You could create a mapper function, that takes your key function and returns another function, applying the key function to each element of some iterable.
def mapper(function):
def inner(values):
return tuple([function(x) for x in values])
return inner
Example:
>>>sorted([('Gold', 2), ('Bronze', 1), ('Gold', 1)], key=mapper(custom_key))
[('Gold', 1), ('Gold', 2), ('Bronze', 1)]
Or similar, using functools.partial with map
:
>>> sorted([('Gold', 2), ('Bronze', 1), ('Gold', 1)], key=functools.partial(map, custom_key))
[('Gold', 1), ('Gold', 2), ('Bronze', 1)]