【问题标题】:Complex sort of a list of dicts by key: ascending and descending for every tuple of key's value按键列表的复杂排序:键值的每个元组的升序和降序
【发布时间】:2019-03-22 08:28:19
【问题描述】:

我有一个字典列表,我想按它的“段”键排序,它们是元组列表:

example = [{'segment': [(329, 363), (379, 397)], 'name': '1'},
           {'segment': [(329, 336), (339, 341), (396, 399)], 'name': '2'},
           {'segment': [(329, 363), (379, 399)], 'name': '3'},
           {'segment': [(329, 336), (337, 357), (396, 399)], 'name': '4'}]

排序后的列表应如下所示:

sorted_example = [{'segment': [(329, 363), (379, 399)], 'name': '3'},
                  {'segment': [(329, 336), (337, 357), (396, 399)], 'name': '4'},
                  {'segment': [(329, 336), (339, 341), (396, 399)], 'name': '2'},
                  {'segment': [(329, 363), (379, 397)], 'name': '1'}]

我想要的输出以某种方式排序,我可以轻松检查 dict[n+1] 是否完全包含在 dict[n] 中。

所以首先我想按第一个元组的第一个元素升序排序,然后按最后一个元组的第二个元素降序。
这对于像 dict 1 和 3 这样的情况是可以的,但是对于像 2 和 4 这样的其他 dicts,我必须遍历所有元组并按其第一个元素升序并按其第二个元素降序排序。

我实现第一步的代码是:

sorted_example = sorted(example, key=lambda k: (k['segment'][0][0], -k['segment'][-1][1]))

但我不知道如何遍历一个列表中的所有元组并按上述升序和降序对它们进行排序。

如果有人能给我提示,我会非常非常高兴!

【问题讨论】:

  • 我仍然没有得到排序逻辑。为什么 dict 3 是排序列表中的第一个,而 dict1 是最后一个?
  • 是什么让 dict 4 出现在 dict2 之前?
  • 我的第一个排序步骤查看第一个元组的第一个元素并将它们升序排序。由于这里的所有值都相同,因此没有问题。接下来,字典按最后一个元组的第二个元素按降序排序,因此 dict 1 的 397 使该字典成为最后一个元素,因为最后一个元组的每隔一个第二个元素都大于 397。
  • 在我的第二步中,这个排序逻辑适用于每个列表的每个元组:所以第一个元组的 363 使 dict 3 成为第一个 dict(第二个元组元素的降序!),而第一个元素dict 4 的第二个元组的第一个元素低于 dict 2 的第二个元组的第一个元素(337

标签: python python-3.x sorting


【解决方案1】:

您可以使用生成器表达式迭代字典中给定子列表的元组,并返回一个项的元组,其中第二项取反,以便按降序排序。将生成器表达式解包到键函数的输出元组中,以便在为您的第一条规则放置的项目之后考虑它:

sorted(example, key=lambda k: (k['segment'][0][0], -k['segment'][-1][1], *((a, -b) for a, b in k['segment'])))

这会返回:

[{'segment': [(329, 363), (379, 399)], 'name': '3'},
 {'segment': [(329, 336), (337, 357), (396, 399)], 'name': '4'},
 {'segment': [(329, 336), (339, 341), (396, 399)], 'name': '2'},
 {'segment': [(329, 363), (379, 397)], 'name': '1'}]

【讨论】:

  • 太棒了,非常感谢!我之前对生成器表达式只有一个模糊的概念。这也将简化我的一些其他代码!
  • 如果我只想按生成器表达式对字典进行排序,那么正确的语法是什么? (没有k['segment'][0][0], -k['segment'][-1][1])我尝试了很多变体,但仍然只有语法错误......
  • 在这种情况下,您可以将生成器表达式传递给元组构造函数:sorted(example, key=lambda k: tuple((a, -b) for a, b in k['segment']))
猜你喜欢
  • 2021-09-29
  • 1970-01-01
  • 2020-12-10
  • 2021-05-19
  • 1970-01-01
  • 2020-02-08
  • 2011-08-25
  • 1970-01-01
  • 2016-10-18
相关资源
最近更新 更多