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)
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.
我有完全相同的问题,并设计了一个轻量级的通用解决方案:
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
| 归档时间: |
|
| 查看次数: |
15803 次 |
| 最近记录: |