这是一个解决方案,它将reverse 分别应用于True 和False 的-1 和1,应用于每个属性的有序 版本 - 因为很可能该字符串属性多于一个字符。这个想法是创建一个可以传递给sorted() 的key 函数。
编辑:这是multilevel_order 应用不同反转规则的版本(注意名称更改):
def multilevel_order(reverse):
multipliers = tuple(-1 if trufal else 1 for trufal in reverse)
def key_func(item):
return tuple(tuple(map(m.__mul__, map(ord, attr))) for attr, m in zip(item, multipliers))
return key_func
结果:
items = [('a', 'b', 'c'), ('a', 'c', 'b'), ('a', 'b', 'b'),
('b', 'a', 'a'), ('b', 'a', 'b'), ('b', 'b', 'b')]
reverse = (True, False, True)
expected = [('b', 'a', 'b'), ('b', 'a', 'a'), ('b', 'b', 'b'),
('a', 'b', 'c'), ('a', 'b', 'b'), ('a', 'c', 'b')]
print(sorted(items, key=multilevel_order(reverse)) == expected)
# True
items = [('a', 'c'), ('b', 'a'), ('a', 'b'), ('b', 'b'), ('a', 'a')]
reverse = (True, False) # first level descending, second level ascending
expected = [('b', 'a'), ('b', 'b'), ('a', 'a'), ('a', 'b'), ('a', 'c')]
print(sorted(items, key=multilevel_order(reverse)) == expected)
# True
原始答案:我还使用了items 的稍微修改的值,以使ordinaled 的效果更清晰。
items = [('a', 'bb', 'ccc'), ('a', 'cc', 'bbb'), ('a', 'bb', 'bbb'),
('b', 'aa', 'aaa'), ('b', 'aa', 'bbb'), ('b', 'bb', 'bbb')]
reverse = (True, False, True)
multipliers = tuple(-1 if trufal else 1 for trufal in reverse)
def multi_level_key(item):
ordinaled = (map(ord, attr) for attr in item)
# this multiplication step could have been included above
return tuple(tuple(map(m.__mul__, o)) for m, o in zip(multipliers, ordinaled))
multi_level_key() 的示例输出:
[multi_level_key(item) for item in items]
# output:
[((-97,), (98, 98), (-99, -99, -99)),
((-97,), (99, 99), (-98, -98, -98)),
((-97,), (98, 98), (-98, -98, -98)),
((-98,), (97, 97), (-97, -97, -97)),
((-98,), (97, 97), (-98, -98, -98)),
((-98,), (98, 98), (-98, -98, -98))]
将其用作key 的sorted():
sorted(items, key=multi_level_key)
# output:
[('b', 'aa', 'bbb'),
('b', 'aa', 'aaa'),
('b', 'bb', 'bbb'),
('a', 'bb', 'ccc'),
('a', 'bb', 'bbb'),
('a', 'cc', 'bbb')]
潜在的改进:我将multipliers 移出关键功能,使其只计算一次。理想情况下,它应该放在multi_level_key() 的闭包中,这样它就可以与其他反转规则一起使用,而无需编写新函数。