【问题标题】:Sorting a list of lists of dictionaries in python在python中对字典列表列表进行排序
【发布时间】:2016-06-11 21:21:18
【问题描述】:

我有一个对象是字典列表:

myObject =[[{ "play": 5.00, "id": 1, "uid": "abc" },  \
            { "play": 1.00, "id": 2, "uid": "def" }], \
           [{ "play": 6.00, "id": 3, "uid": "ghi" },  \
            { "play": 7.00, "id": 4, "uid": "jkl" }], \
           [{ "play": 3.00, "id": 5, "uid": "mno" },  \
            { "play": 1.00, "id": 6, "uid": "pqr" }]]

我想按每个嵌套列表的字典中play 值的总和对列表进行排序。然后该对象将按如下方式排序:

myObject =[[{ "play": 6.00, "id": 3, "uid": "ghi" },  \
            { "play": 7.00, "id": 4, "uid": "jkl" }], \
           [{ "play": 5.00, "id": 1, "uid": "abc" },  \
            { "play": 1.00, "id": 2, "uid": "def" }], \
           [{ "play": 3.00, "id": 5, "uid": "mno" },  \
            { "play": 1.00, "id": 6, "uid": "pqr" }]]

如果它只是一个字典列表,那么:

sorted(myObject, key=sum(map(itemgetter(play))), reverse=True)

会起作用的。如果不遍历列表、计算总和然后排序,我无法弄清楚如何做到这一点。这就是我现在正在做的事情,但我正试图通过删除循环来提高这段代码的效率,因为我的列表中有数以百万计的列表。

【问题讨论】:

  • 请注意:在这种情况下,您不需要尾随 \ 行继续。由于行以逗号结尾并且列表文字仍然“打开”,Python 将自动期望下一行继续在那里。

标签: python list sorting dictionary


【解决方案1】:

你的想法已经很不错了,在排序和使用summapitemgetter时使用自定义键功能play键:

key=sum(map(itemgetter(play)))

你确实有一个问题:key 参数需要一个函数来获取你正在排序的列表中的一项。但是summap 都没有返回一个函数,所以你不能把它作为一个关键函数。相反,您可以创建一个 lambda 函数,为每个项目执行此组合。

其他问题是play 应该是一个字符串'play',而map 应该将子列表作为参数。所以你的关键功能应该是这样的:

key=lambda x: sum(map(itemgetter('play'), x))

这是顺便说一句。功能上等同于以下可能更具可读性的生成器理解:

key=lambda x: sum(y['play'] for y in x)

将其与sorted 一起使用应该可以,但您应该考虑直接使用list.sort 对列表进行排序:

>>> myObject = [[{ "play": 5.00, "id": 1, "uid": "abc" },
                 { "play": 1.00, "id": 2, "uid": "def" }],
                [{ "play": 6.00, "id": 3, "uid": "ghi" },
                 { "play": 7.00, "id": 4, "uid": "jkl" }],
                [{ "play": 3.00, "id": 5, "uid": "mno" },
                 { "play": 1.00, "id": 6, "uid": "pqr" }]]

>>> myObject.sort(key=lambda x: sum(y['play'] for y in x), reverse=True)

>>> for x in myObject:
        print(x)

[{'play': 6.0, 'uid': 'ghi', 'id': 3}, {'play': 7.0, 'uid': 'jkl', 'id': 4}]
[{'play': 5.0, 'uid': 'abc', 'id': 1}, {'play': 1.0, 'uid': 'def', 'id': 2}]
[{'play': 3.0, 'uid': 'mno', 'id': 5}, {'play': 1.0, 'uid': 'pqr', 'id': 6}]

(顺便说一句。myObject 是一个不好的名字。)


就您的问题的效率或复杂性而言,您确实无法避免最终必须遍历每个子列表。如果不查看这些值,就不可能确定这些值的总和,因此显然您无法避免这种情况。

但是,您应该确保每个总和只计算一次,以避免多次查看子列表中的项目。幸运的是,使用list.sort 的默认排序确实可以保证:

列表中每一项对应的key只计算一次,然后用于整个排序过程。

因此,您将对这个排序问题有一个非常有效的解决方案。

【讨论】:

  • 不应该是reverse=True先拿到最高吧
  • @PaulRooney 哦,是的,我错过了问题中的那个细节(尽管它与排序问题并不真正相关)。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 2018-05-27
  • 2014-02-14
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
相关资源
最近更新 更多