基于python中嵌套列表中的列表之一进行排序

use*_*511 3 python sorting nested list

我有一个清单 [[4,5,6],[2,3,1]].现在我想根据list[1]输出 排序列表[[6,4,5],[1,2,3]].所以基本上我正在排序2,3,1和维护顺序list[0].

在搜索时,我得到了一个基于每个列表的第一个元素进行排序的函数,但不是为此.此外,我不想重新创建列表[[4,2],[5,3],[6,1]],然后使用该功能.

Lau*_*low 7

由于[4, 5, 6]并且[2, 3, 1]服务于两个不同的目的,我将创建一个带有两个参数的函数:要重新排序的列表,以及排序将决定顺序的列表.我只会返回重新排序的列表.

这个答案有三个不同解决方案的时间,用于创建排序的排列列表.使用最快的选项提供此解决方案:

def pyargsort(seq):
    return sorted(range(len(seq)), key=seq.__getitem__)

def using_pyargsort(a, b):
    "Reorder the list a the same way as list b would be reordered by a normal sort"
    return [a[i] for i in pyargsort(b)]                     

print using_pyargsort([4, 5, 6], [2, 3, 1])    # [6, 4, 5]
Run Code Online (Sandbox Code Playgroud)

pyargsort方法的灵感来自于numpy argsort方法,它可以更快地完成同样的操作.Numpy还具有高级索引操作,可以将数组用作索引,从而可以非常快速地重新排序数组.

因此,如果您对速度的需求很大,那么可以假设这个numpy解决方案会更快:

import numpy as np

def using_numpy(a, b):
    "Reorder the list a the same way as list b would be reordered by a normal sort"
    return np.array(a)[np.argsort(b)].tolist()

print using_numpy([4, 5, 6], [2, 3, 1])     # [6, 4, 5]
Run Code Online (Sandbox Code Playgroud)

但是,对于短列表(长度<1000),此解决方案实际上比第一个慢.这是因为我们首先将ab列表array转换为然后将结果转换回返回list之前.如果我们假设你在整个应用程序中使用numpy数组,这样我们就不需要来回转换了,我们得到了这个解决方案:

def all_numpy(a, b):
    "Reorder array a the same way as array b would be reordered by a normal sort"
    return a[np.argsort(b)]

print all_numpy(np.array([4, 5, 6]), np.array([2, 3, 1]))    # array([6, 4, 5])
Run Code Online (Sandbox Code Playgroud)

all_numpy功能的执行速度比using_pyargsort功能快10倍.

以下对数图将这三种解决方案与其他答案中的两种替代解决方案进行了比较.参数是两个等长的随机混洗范围,并且函数都接收相同排序的列表.我只计算函数执行的时间.为了说明的目的,我为每个numpy解决方案添加了额外的图形行,其中加载numpy的60 ms开销被添加到时间.

在此输入图像描述

正如我们所看到的,这种全能的解决方案比其他解决方案高出一个数量级.相比之下,从python转换list回来会using_numpy大大减慢解决方案的速度,但对于大型列表,它仍然胜过纯python.

对于大约1'000'000的列表长度,using_pyargsort需要2.0秒,using_nympy+开销仅为1.3秒,而all_numpy+开销为0.3秒.

  • 无需为排序列表等简单任务安装第三方库... numpy不是标准python安装的一部分. (3认同)
  • @ l4mpi再次阅读问题.它不是标准排序,而是重新排序列表的第一项,与第二项的标准排序方式相同.此外,downvote*表示*"这个答案没用".如果某人已经使用了numpy,那么这个答案*是有用的,即使没有,它也会提供一个选项.你的downvote是不合适的. (2认同)
  • @ l4mpi我将编辑答案以明确numpy不是标准库的一部分. (2认同)
  • @mgilson现在好些吗? (2认同)

mgi*_*son 5

您描述的排序不是很容易实现.我能想到的唯一方法就是zip用来创建你不想创建的列表:

lst = [[4,5,6],[2,3,1]]
# key = operator.itemgetter(1) works too, and may be slightly faster ...
transpose_sort = sorted(zip(*lst),key = lambda x: x[1])
lst = zip(*transpose_sort)
Run Code Online (Sandbox Code Playgroud)

有这种约束的原因吗?

(另请注意,如果您真的想要,可以在一行中执行此操作:

lst = zip(*sorted(zip(*lst),key = lambda x: x[1]))
Run Code Online (Sandbox Code Playgroud)

这也会产生一个元组列表.如果你真的想要一个列表列表,你可以map得到结果:

lst = map(list, lst)
Run Code Online (Sandbox Code Playgroud)

或者列表理解也会起作用:

lst = [ list(x) for x in lst ]
Run Code Online (Sandbox Code Playgroud)