【问题标题】:Good way to keep a list of lists sorted on second element when appending new elements?添加新元素时保持列表按第二个元素排序的好方法?
【发布时间】:2013-10-01 08:49:58
【问题描述】:

我有一个文件,其中包含我正在循环的值。该文件由具有 x 和 y 值的两列组成。我将 x 和 y 值添加到列表中,例如

example_list = []
for line in f:
    example_list.append([line.split()[0], line.split()[1]])

但是,我希望列表最长为 15 个列表,仅保留来自 line.split()[1] 的最高值。两种方法是

example_list = []
for line in f:
    example_list.append([line.split()[0], line.split()[1]])
top_15 = example_list.sort(key=operator.itemgetter(1), reverse=True)[:15]

example_list = []
count = 0
for line in f:
    if count < 15:
        example_list.append([line.split()[0], line.split()[1]])
        count += 1
    else:
        example_list.sort(key=operator.itemgetter(1))
        if example_list[0][1] < line.split()[1]:
            example_list[0] = line.split()[1]

但是,我不想读取内存中的整个文件或为每一行调用sort。有什么更好的方法来保持列表的排序,以便只添加一个新元素来替换列表中的最低元素?

【问题讨论】:

    标签: python list sorting python-2.7


    【解决方案1】:

    您正在寻找heapq module;堆可让您在进行过程中有效地保留前 N 个项目。甚至还有针对您的确切用例的专用功能:

    from heapq import nlargest
    from operator import itemgetter
    
    largest_15 = nlargest(15, (line.split()[:2] for line in f), itemgetter(1))
    

    这会传入一个生成器表达式,有效地处理循环。

    在底层,这个方法:

    • 获取前 15 个元素并从中创建一个堆。
    • 在堆上调用heappushpop() 以获得以下所有项目;这会将项目添加到堆中,然后删除最小的项目。因此,堆只包含 15 个最大的项目。
    • 当迭代完成时,堆列表被排序。

    【讨论】:

    • lambda x: x[0] 确实比itemgetter(1) 更具可读性/可理解性,尤其是后者需要额外的导入:)
    • @ErikAllik: itemgetter() 更快,而且 OP 已经在使用它
    • 啊,我没注意到。
    • 谢谢。我认为largest_15 = nlargest(15, (line.split()[:1] for line in f), itemgetter(1)) 必须是largest_15 = nlargest(15, (line.split() for line in f), itemgetter(1)),否则只会选择第一列。
    • @NiekdeKlein:对不起,是的。我的意思是[:2],因为这就是您的原始代码本质上所做的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 2021-04-21
    • 2012-03-13
    • 1970-01-01
    相关资源
    最近更新 更多