如何通过子列表的反向长度对嵌套列表进行排序并保留原始顺序

时间:2017-12-08 11:02:06

标签: python python-3.x list sorting

示例:

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)

(它反转了子列表'删除'以及'列')

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

1 个答案:

答案 0 :(得分:4)

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函数或lambda s。

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