首页 > 解决方案 > 在 Python 3 中按不同类型对 dict 列表进行排序

问题描述

我有一种方法可以通过键对 dict 列表进行分组。为此,我在这里发现我必须使用该groupby功能,但在我必须对列表进行排序之前。这是我现在的方法:

def group_list_by_key(data, key):
    data.sort(key=lambda x: x[key])
    result = []
    for k, v in groupby(data, key=lambda x: x[key]):
        result.append(list(v))
    return result

仅当在所有 dicts 中定义了每个键并且值都是相同类型时,这段代码才有效。但是,在我使用这种方法的地方,我不知道是否到处都定义了密钥以及它们是否属于同一类型。在 Python 2.x 上,我知道存在sorted带有cmp参数的函数可以进行自定义排序,但是从Python 3.x 开始,这不再可能了。有没有办法进行自定义排序?我正在考虑使用经典的排序方式<并按类型名排序。

到目前为止,我考虑过使用 get 函数并以类似的方式转换为字符串

data.sort(key=lambda x: str(x.get(key)))
...
for k, v in groupby(data, key=lambda x: x.get(key)):

它只在字符串、数字和无内容的情况下克服,但不是通用对象,如果例如我执行它很容易中断

a = [{'b': 0, 'c': 1}, {'b': '0'}, {'b': 0, 'c': 2}, {'b': 1}, {'c': 3}]
group_list_by_key(a, 'b')

输出是

[[{'b': 0, 'c': 1}], [{'b': '0'}], [{'b': 0, 'c': 2}], [{'b': 1}], [{'c': 3}]]

而不是我所期望的(列表的顺序不是问题)

[[{'b': 0, 'c': 1}, {'b': 0, 'c': 2}], [{'b': '0'}], [{'b': 1}], [{'c': 3}]]

标签: pythonpython-3.xsorting

解决方案


你可以通过做这样的事情来解决你的问题

data = [{'b': 0, 'c': 1}, {'b': '0'}, {'b': 0, 'c': 2}, {'b': 1}, {'c': 3}]
key='b'

def f(x):
     ret = x.get(key, -1)
     return ret if type(ret) == int else -2

result = [list(v) for k, v in groupby(sorted(data, key=f), f)]

# result: [[{'b': '0'}], [{'c': 3}], [{'b': 0, 'c': 1}, {'b': 0, 'c': 2}], [{'b': 1}]]

但是如果您仍然需要自定义比较功能,您可以使用functools.cmp_to_key

import functools
sorted(x, key=functools.cmp_to_key(custom_cmp_function))

推荐阅读