【问题标题】:Sort list of Dict By Multiple Keys, Including List按多个键排序字典列表,包括列表
【发布时间】:2019-04-05 07:43:46
【问题描述】:

我想按列表键然后按日期对这个字典列表进行排序。 我正在尝试根据 label_order 按“标签”对字典进行排序,然后按“日期”降序排列。

label_order = [3, 4, 2, 1]

data = [
    {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
    {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
    {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
]

排序后会是这样的:

data = [
    {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
    {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
    {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
    {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
    {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
]

我已经尝试过 lambda 表达式和 itemgetter,但我很难为排序键组合正确的策略。也许它只是想一次做太多事情。

任何帮助或指导将不胜感激。

【问题讨论】:

  • 提示:label_order.index(item['label']) 返回该列表中每个项目标签的索引,该索引对应于其排序顺序。
  • 让我们看看最接近预期结果的 lambda
  • 我会将label_order 更改为将标签映射到其排序位置的字典。 IE。先是 3,然后是 4,所以应该是{3:1, 4:2, 2:3, 1:4}

标签: python sorting


【解决方案1】:

一种更有效的方法是构建一个将label_order 中的项目映射到索引的dict,以便在执行排序时可以将索引用作键:

keys = {n: i for i, n in enumerate(label_order)}
sorted(data, key=lambda d: (-keys[d['label']], d['date']), reverse=True)

这会返回:

[{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
 {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
 {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
 {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
 {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)}]

【讨论】:

    【解决方案2】:

    以相反的顺序对日期进行排序有点棘手。相反,让我们使用标签索引的 negative,以便它们按降序排序。然后我们就可以逆序排序,按照我们真正想要的顺序得到结果!

    from datetime import datetime
    
    label_order = [3, 4, 2, 1]
    
    data = [
        {'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
        {'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
        {'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
        {'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
        {'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
    ]
    
    def descending_sort_key(item):
        return -label_order.index(item['label']), item['date']
    
    data.sort(key=descending_sort_key, reverse=True)
    

    瞧 - 没有日期数学或其他诡计。

    【讨论】:

      猜你喜欢
      • 2014-02-11
      • 2016-08-06
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      相关资源
      最近更新 更多