【问题标题】:How to keep a list of lists sorted as it is created如何在创建列表时保持列表的排序
【发布时间】:2012-09-01 17:05:33
【问题描述】:

我正在读取一个文件并在 Python 中提取包含一些字符串和一些数字的数据。我将此信息存储为列表列表,如下所示:

dataList = [

['blah', 2, 3, 4],

['blahs', 6, 7, 8],

['blaher', 10, 11, 12],

]

我想让dataList按子列表的第二个元素排序:dataList[][1]

我想当我想添加它们时可以使用 insort 或 bisect,但我不知道如何让它查看子列表的第二个元素。

这里有什么想法吗?我只是将数据附加到末尾,然后进行线性排序以稍后再查找内容。但是,在这里扔几十个数千个子列表,然后搜索 100k 个项目,这需要一段时间。

【问题讨论】:

  • 为什么不能只添加所有内容然后对结果进行排序?在我看来,边走边排序效率会降低......
  • 我曾考虑过这一点,但认为在添加项目时保持排序会更有效。也许不是?
  • @ErikS 在 python 列表中间的插入是 O(n)
  • 如果您真的希望它在创建时保持排序,请查看code.activestate.com/recipes/577197-sortedcollection
  • 你所描述的相当于insertion sort,它的运行时间为O(n^2)。大多数好的排序算法(如merge sortquicksort)在O(n log n) 时间内运行。因此,在进行过程中保持排序并不会更有效。

标签: python data-structures multidimensional-array sorting


【解决方案1】:
dataList.sort(key=lambda x: x[1])

这会按每个项目中的第二个元素对列表进行适当的排序。

正如 cmets 中所指出的,仅排序一次(在最后)效率更高。 Python 的内置排序方法已经过高度优化以快速运行。经过测试,在各种大小的列表中,内置排序似乎始终比使用另一个答案中建议的heap method 快 3.7 倍左右(我测试了高达 600000 的大小)。

【讨论】:

  • 这并没有解决 OP 关于在创建列表时保持排序的问题。
  • 对,我会遇到这个。在所有数据之后进行排序是否比保留排序列表更有效?
  • @ErikS:是的,这可能更有效。它的时间复杂度与 heap-insert-then-pop 答案相同,但系数和常数项可能要小得多。如果你真的关心性能,我会测试它!
  • @ErikS 一项快速实验(在 1000 个长度为 10000 的列表上)表明堆方法比 Python 专门构建的排序慢 3.5 倍。
【解决方案2】:

取决于几件事,但首先想到的是使用 heapq 模块:

import heapq
heap = []
for row in rows:
    heapq.heappush(heap, (row[1], row))

这将创建一个充满元组的堆,其中第一个元素是您要排序的元素,第二个元素是行。

从堆中读取它们的最简单方法是复制它然后弹出项目:

new_heap = list(heap)
while new_heap:
    _, row = heapq.heappop(new_heap)
    print row

将每个项目插入堆的运行时间是O(lg N),所以创建堆需要O(N lg N)时间,从堆中弹出项目也需要O(lg N)时间,所以需要O(N lg N)时间遍历它。

如果这些权衡不理想,您可以使用二叉搜索树(标准库中不存在,但 they are easy to find),或者按照其他评论者的建议,在阅读后对行进行排序:rows.sort(key=lambda row: row[1])

现在,在实践中,除非您要处理大量行,否则在加载列表后对列表进行就地排序几乎肯定会更快(即,使用.sort() 方法)......所以试试一些事情,看看什么最有效。

最后,bisect 是个糟糕的主意,因为插入 Python 列表需要 O(N) 时间,所以使用 bisect 插入项目需要 O(N lg N) 时间每个项目,所以总时间为O((N lg N) * N) = O(N**2)时间。

【讨论】:

  • 在实践中(在 Python 中)我怀疑这比创建列表然后对其进行排序更快,尽管它值得测试。
  • @DavidRobinson 这不是更快,而是慢得多。 Python 的排序已经过大量优化!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2020-12-20
  • 2023-03-05
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多