python-如何按子列表的反向长度对嵌套列表进行排序并保持原始顺序

例:

a = 
[
[['test', 21, 28], ['test', 61, 68], ['test', 111, 118], ['test', 118, 125]],
[['Columns', 21, 28], ['Columns', 61, 68], ['Columns', 111, 118], ['Columns', 118, 125], ['Columns', 128, 135]], 
[['Delete', 14, 20], ['Delete', 47, 53], ['Delete', 54, 60], ['Delete', 78, 84], ['Delete', 95, 101]], 
[['rw', 21, 28], ['rw', 61, 68], ['rw', 111, 118]]
]

我想要做的是按照子列表的长度反转来对嵌套列表进行排序
但如果子列表的长度相同,则保持原始顺序.

预期结果:

[
[['Columns', 21, 28], ['Columns', 61, 68], ['Columns', 111, 118], ['Columns', 118, 125], ['Columns', 128, 135]], 
[['Delete', 14, 20], ['Delete', 47, 53], ['Delete', 54, 60], ['Delete', 78, 84], ['Delete', 95, 101]], 
[['test', 21, 28], ['test', 61, 68], ['test', 111, 118], ['test', 118, 125]], 
[['rw', 21, 28], ['rw', 61, 68], ['rw', 111, 118]]
]

我知道我可以使用它按反向长度对列表进行排序,但它不会保持原始顺序:

a = sorted(a, key=len, reverse=True)

(它会颠倒子列表“删除”和“列”)

如何按子列表的反向长度对列表进行排序并保持原始顺序?

最佳答案

TimSort是一种稳定的排序,因此通常保留相等项目的顺序.因此,您的代码应该可以正常工作.

或者,摆脱reverse = True并使用返回子列表长度为负数的键函数.

a = [
    [['test', 21, 28], ['test', 61, 68], ['test', 111, 118], ['test', 118, 125]],
    [['Columns', 21, 28], ['Columns', 61, 68], ['Columns', 111, 118], ['Columns', 118, 125], ['Columns', 128, 135]],    
    [['Delete', 14, 20], ['Delete', 47, 53], ['Delete', 54, 60], ['Delete', 78, 84], ['Delete', 95, 101]], 
    [['rw', 21, 28], ['rw', 61, 68], ['rw', 111, 118]]
]

a.sort(key=lambda x: -len(x))
for row in a:
    print(row)

输出

[['Columns', 21, 28], ['Columns', 61, 68], ['Columns', 111, 118], ['Columns', 118, 125], ['Columns', 128, 135]]
[['Delete', 14, 20], ['Delete', 47, 53], ['Delete', 54, 60], ['Delete', 78, 84], ['Delete', 95, 101]]
[['test', 21, 28], ['test', 61, 68], ['test', 111, 118], ['test', 118, 125]]
[['rw', 21, 28], ['rw', 61, 68], ['rw', 111, 118]]

如果我用

a.sort(key=len, reverse=True)

我得到与上述相同的输出.如果您也没有得到该输出,则说明很奇怪.请注意,此版本比上面的版本更有效,因为它直接调用len(在C中实现,并且执行快速属性查找以确定对象的长度),并且Python函数调用相对较慢,无论它们是否为def函数.或lambdas.

顺便说一句,当您想就地对列表进行排序时,应始终调用其.sort方法.内置的sorted函数实际上会创建一个新列表,将原始数据复制到该列表,然后对其调用.sort,然后将新列表绑定到目标.因此,避免创建该副本并在原始列表上自行调用.sort会更有效率.