【问题标题】:Sorting a list of tuples does not sort them actually对元组列表进行排序实际上并不对它们进行排序
【发布时间】:2021-01-05 13:35:47
【问题描述】:

假设我有一本这样的字典:

a = {1:"a", 3:"c", 5:"e", 4:"d" ,2:"b", 6:"f", 7:"g"}

然后我将其转换为元组列表:

b = list(a.items())

现在,我想根据元组的第一个值对列表进行排序。我有三种方法:

from operator import itemgetter
b.sort(key=itemgetter(0))

b.sort(key=lambda x: x[::-1])
b = sorted(b, key=lambda t: (t[0]))

在任何一种情况下,如果我打印b,我都会得到排序列表:

print(b)

>>> [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g')]

但是,如果我在进程中实际使用b,结果是它没有排序。我测试了一些东西,但目前我手头的东西是这样的:

batch_count = len(b) // 3
batches = [[] for _ in range(batch_count)]
for index, vec in enumerate(b):
    batches[index % batch_count].append(vec)

这会将 b 组合到至少 3 个列表中。但是,如果我打印 batches,我会从 a 获得原始订单,但预期的 7 除外。

print(batches)

>>> [[(1, 'a'), (3, 'c'), (5, 'e'), (7, 'g')], [(2, 'b'), (4, 'd'), (6, 'f')]]

有谁知道为什么以及如何防止这种情况发生?

【问题讨论】:

  • 输出正是你应该得到的;您原来的 dict 具有几乎相同的订单(忽略批次边界)这一事实是巧合。
  • 您期望得到什么输出?将b 的元素分组,自然会改变它们的顺序。请注意,每个组的顺序仍然正确。

标签: python python-3.x sorting tuples


【解决方案1】:

这不是同一个顺序。由于index % batch_count,它被偶数/奇数位置分割。

batch_count 为 2,则您有 index % 2,它将在 01 之间交替:

>>> [i % 2 for i in range(10)]
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

最终结果是在第一个子集合中保持偶数位置,在第二个子集合中保持赔率。

【讨论】:

  • 我刚刚用另一个 dict 测试过,你是对的!我在这上面花了大约一个小时,却没有意识到!我真笨!谢谢!
  • 没问题。如有疑问,请检查您的中间数据。对于分组,请查看itertools 文档中的食谱部分。那里可能有一个现有的解决方案可以帮助您。这是一个很棒的模块。
【解决方案2】:

输出正常。完全不用排序就可以试一试,看看有什么区别。

batch_count = len(b) // 3
batches = [[] for _ in range(batch_count)]
for index, vec in enumerate(b):
    batches[index % batch_count].append(vec)

根据您的情况从原始列表创建两个子列表,即偶数和赔率。它们中的每一个都是排序的。

【讨论】:

    【解决方案3】:

    您可以使用grouper 函数将列表拆分为大小为n 的列表。

    from itertools import zip_longest
    
    def grouper(n, iterable):
        args = [iter(iterable)] * n
        return ([e for e in t if e != None] for t in zip_longest(*args))
    
    b = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g')]
    batches = list(grouper(3, b))
    print(batches)
    

    输出:

    [[(1, 'a'), (2, 'b'), (3, 'c')], [(4, 'd'), (5, 'e'), (6, 'f')], [(7, 'g')]]
    

    【讨论】:

    • 虽然我喜欢你的想法,但事实上它创建了一个只有第一条记录具有值的可迭代对象,然后循环它提供了不必要的开销。因此,for 循环的工作速度更快。虽然,非常轻微。不过,一个非常好的解决方案。谢谢!
    • @mnsr 如果你在修改你的 for 循环后也达到了同样的效果,那么请保留它。此解决方案更通用,适用于您希望按数字分组的每种类型的列表。开销可以忽略不计。感谢您的支持,干杯:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    相关资源
    最近更新 更多