如何自定义要在json.dumps中使用的dict列表

WoJ*_*WoJ 17 python sorting json dictionary list

我有一个类似的列表

allsites = [
    {
        'A5': 'G', 
        'A10': 'G', 
        'site': 'example1.com', 
        'A1': 'G'
    }, 
    {
        'A5': 'R', 
        'A10': 'Y',
        'site': 'example2.com', 
        'A1': 'G'
    }
]
Run Code Online (Sandbox Code Playgroud)

我用的是json.dumps:

data = { 'Author':"joe", 'data':allsites }
print json.dumps(data,sort_keys=True,indent=4, separators=(',', ': '))
Run Code Online (Sandbox Code Playgroud)

这会输出以下JSON:

{
    "Author": "joe",
    "data": [
        {
            "A1": "G",
            "A10": "G",
            "A5": "G",
            "site": "example1.com"
        },
        {
            "A1": "G",
    (...)
Run Code Online (Sandbox Code Playgroud)

我希望通过自定义键("alphabet")对此JSON字符串的"data"部分进行排序,在上面的情况下,这将是site, A1, A5, A10实际上看起来像:

{
    "Author": "joe",
    "data": [
        {
            "site": "example1.com",
            "A1": "G",
            "A5": "G",
            "A10": "G"
        },
        {
            "site": "example2.com",
            "A1": "G",
    (...)
Run Code Online (Sandbox Code Playgroud)

我在Sorting FAQ中读到了自定义排序,但它只是提供了一种覆盖比较函数的方法,更不用说我不知道​​如何将它插入到我的代码中.

怎么做?

ale*_*cxe 25

由于python dicts是无序集合,因此使用collections.OrderedDict自定义排序:

from collections import OrderedDict
import json

allsites = [
    {
        'A5': 'G',
        'A10': 'G',
        'site': 'example1.com',
        'A1': 'G'
    },
    {
        'A5': 'R',
        'A10': 'Y',
        'site': 'example2.com',
        'A1': 'G'
    }
]

sort_order = ['site', 'A1', 'A5', 'A10']
allsites_ordered = [OrderedDict(sorted(item.iteritems(), key=lambda (k, v): sort_order.index(k)))
                    for item in allsites]

data = {'Author': "joe", 'data': allsites_ordered}
print json.dumps(data, indent=4, separators=(',', ': '))
Run Code Online (Sandbox Code Playgroud)

打印:

{
    "data": [
        {
            "site": "example1.com",
            "A1": "G",
            "A5": "G",
            "A10": "G"
        },
        {
            "site": "example2.com",
            "A1": "G",
            "A5": "R",
            "A10": "Y"
        }
    ],
    "Author": "joe"
}
Run Code Online (Sandbox Code Playgroud)

  • 不要为python3工作更多,@alecxe,它说:“python 3不支持元组参数解包”。见斯科特回答。 (2认同)

Sco*_*lby 10

在Python3中,alecxe的答案不再适用.这应该是一个评论,但我缺乏声誉.

PEP 3113删除了函数签名中的元组解包,所以该行

allsites_ordered = [OrderedDict(sorted(item.iteritems(), key=lambda (k, v): sort_order.index(k)))
                    for item in allsites]
Run Code Online (Sandbox Code Playgroud)

现在必须

allsites_ordered = [OrderedDict(sorted(item.items(), key=lambda item: sort_order.index(item[0])))
                    for item in allsites]
Run Code Online (Sandbox Code Playgroud)

或类似的.iteritems也变得公正items.

  • 小更新:从 Python 3.7 开始,`dict` 是默认排序的,我们*可以*依赖它——它已成为规范的一部分。对于使用“OrderedDict”作为您正在使用排序属性的语义指示符,仍然存在争议。此外,`OrderedDict` 保留了内置的 `dict` 仍然缺乏的额外的 `popitem()` 和 `move_to_end()` 方法。此答案中的更多详细信息:/sf/answers/3561079721/ (2认同)

Ari*_*ide 5

我有完全相同的问题,并设计了一个轻量级的通用解决方案:

from collections import OrderedDict

def make_custom_sort(orders):
    orders = [{k: -i for (i, k) in enumerate(reversed(order), 1)} for order in orders]
    def process(stuff):
        if isinstance(stuff, dict):
            l = [(k, process(v)) for (k, v) in stuff.items()]
            keys = set(stuff)
            for order in orders:
                if keys.issuperset(order):
                    return OrderedDict(sorted(l, key=lambda x: order.get(x[0], 0)))
            return OrderedDict(sorted(l))
        if isinstance(stuff, list):
            return [process(x) for x in stuff]
        return stuff
    return process
Run Code Online (Sandbox Code Playgroud)

首先,创建自定义顺序排序函数的实例:

custom_sort = make_custom_sort([ ["site", "A1", "A5", "A10"] ])
Run Code Online (Sandbox Code Playgroud)

现在,实际排序:

result = custom_sort(allsites)
Run Code Online (Sandbox Code Playgroud)

...您可以转储为JSON对象:

print json.dumps(result, indent=4)
Run Code Online (Sandbox Code Playgroud)

结果

[
    {
        "site": "example1.com", 
        "A1": "G", 
        "A5": "G", 
        "A10": "G"
    }, 
    {
        "site": "example2.com", 
        "A1": "G", 
        "A5": "R", 
        "A10": "Y"
    }
]
Run Code Online (Sandbox Code Playgroud)

更多

闭包是递归的.如双括号所示,您可以指定与您的结构中嵌套的各种字典所需的排序顺序一样多.

GitHub项目:https://github.com/laowantong/customsort