When sorting by multiple keys, I need the second key to alternate between standard and reverse sorting. This is to minimize the change in the second key. For example, if I have a list of dictionaries, I want the first sort (group key) to be sorted and then the second sort (sort key) to alternate. This should produce a sort like this: [{'group': 'a', 'sort': 1}, {'group': 'a', 'sort': 2}, {'group': 'a', 'sort': 2}, {'group': 'b', 'sort': 2}, {'group': 'b', 'sort': 1}, {'group': 'b', 'sort': 1}, {'group': 'c', 'sort': 1}, {'group': 'c', 'sort': 1}, {'group': 'c', 'sort': 2}] That limits the change in the field called "sort" as it alternates each time as the "group" changes. I have looked around and did not see a standard way to accomplish this without rolling my own. I think the code is fairly straight forward but curious if I might be missing something or an easier/faster way. Any comments would be appreciated. #!/usr/bin/env python3 """ Misc sort routines """ from operator import itemgetter import pprint def alternate_sort(data, group_key, sort_key, group_reverse=False, sort_reverse=False): """ Sort data within groups while alternating asc/desc on sort key. """ partitions = [] # Tuples of start/end indexes per group last_key = None # Remember when groups change group_start = 0 # Remember start index of group final_sort = [] # The final sorted listing # Make sure the data is sorted by group data = sorted(data, key=itemgetter(group_key), reverse=group_reverse) # Gather the group partitions for i, g in enumerate(data): # When the group changes if last_key != g[group_key]: # End the previous group partition if there is one if i > 0: partitions.append((group_start, i)) # Start a new group partition group_start = i last_key = g[group_key] # Close the last group partition partitions.append((group_start, len(data))) # Go through the partitions, alternate the sort each time using sort key. for i, p in enumerate(partitions): part = data[p[0]: p[1]] if i % 2 == 0: final_sort += sorted( part, key=itemgetter(sort_key), reverse=sort_reverse) else: final_sort += sorted( part, key=itemgetter(sort_key), reverse=not sort_reverse) return final_sort if __name__ == "__main__": unsorted_data = [ {"group": "a", "sort" : 1}, {"group": "a", "sort" : 2}, {"group": "b", "sort" : 2}, {"group": "b", "sort" : 1}, {"group": "c", "sort" : 1}, {"group": "a", "sort" : 2}, {"group": "c", "sort" : 2}, {"group": "b", "sort" : 1}, {"group": "c", "sort" : 1} ] sorted_data = alternate_sort(unsorted_data, "group", "sort", group_reverse=True, sort_reverse=True) pprint.pprint(sorted_data) sorted_data = alternate_sort(unsorted_data, "group", "sort") pprint.pprint(sorted_data)