递归方法:按第一个条件对列表进行排序。然后按该条件分组,并使用剩余的条件递归排序每个子组。
from operator import itemgetter
import itertools
def multisorted(seq, indices, reversed_states):
if len(indices) == 0:
return seq
index = indices[0]
reversed = reversed_states[0]
partially_sorted_seq = sorted(seq, key = itemgetter(indices[0]), reverse=reversed_states[0])
result = []
for key, group in itertools.groupby(partially_sorted_seq, key=itemgetter(indices[0])):
result.extend(multisorted(group, indices[1:], reversed_states[1:]))
return result
d = ((1, 'c', 'aa'),
(2, 'b', 'bb'),
(1, 'c', 'cc'),
(1, 'd', 'dd'))
print(multisorted(d, (0,1,2), (False, True, True)))
结果:
[(1, 'd', 'dd'), (1, 'c', 'cc'), (1, 'c', 'aa'), (2, 'b', 'bb')]
方法2。
sort
和
sorted
已经可以按多个条件进行排序。我们只需要更改键,使每个元组的某些元素在不相等比较方面具有颠倒的逻辑。
from functools import total_ordering
@total_ordering
class Negated:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value > other.value
def multisorted(seq, ordering):
return sorted(seq, key = lambda t: [Negated(x) if reversed else x for x, reversed in zip(t, ordering)])
d = ((1, 'c', 'aa'),
(2, 'b', 'bb'),
(1, 'c', 'cc'),
(1, 'd', 'dd'))
print(multisorted(d, (False, True, True)))