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 key functions sorted([x, y, z], key=custom_key) to implement special sorting criteria.
For example:
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
Could sort any list of strings normally, and also gold/silver/bronze according to my custom ordering.
But it does not "correctly" handle tuples anymore: sorted([('Gold', 2), ('Bronze', 1), ('Gold', 1)], key=custom_key) results in [('Bronze', 1), ('Gold', 1), ('Gold', 2)] as item is not a basestring.
But I would like to get [('Gold', 1), ('Gold', 2), ('Bronze', 1)] by somehow applying the custom logic to each item in the tuple.
What's the best way to "map" the custom key logic over any tuples (that may or may not appear) in the list like the default key function does?
Edit: More examples:
sorted(['Silver', 'Bronze', 'Gold'], key=custom_key)['Gold', 'Silver', 'Bronze']
sorted([['Silver', 2], ['Silver', 1], ['Gold', 1]], key=custom_key)[['Gold', 1], ['Silver', 1], ['Silver', 2]]
sorted([(2, 'Gold'), (2, 'Bronze'), (1, 'Gold')], key=custom_key)[(1, 'Gold'), (2, 'Gold'), (2, 'Bronze')]
sorted([('Silver', 'Bronze'), ('Gold', 'Bronze'), ('Silver', 'Gold')], key=custom_key)[('Gold', 'Bronze'), ('Silver', 'Gold'), ('Silver', 'Bronze')]
custom_keyneeds to handleitembeing either a tuple or string? Why not add anotherisinstance, with a recursive call? Note thatreturn medals_map.get(item, item)is neater than faffing withtryandexcept.itemmight also be a list, or maybe some other iterable? Do I just have to add moreisinstancechecks for all kinds of things? I hoped since the default key function already does all that I can somehow avoid doing that.