23

私は次のようなリストを持っています

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

私が使用するものjson.dumps

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

これにより、次の JSON が出力されます。

{
    "Author": "joe",
    "data": [
        {
            "A1": "G",
            "A10": "G",
            "A5": "G",
            "site": "example1.com"
        },
        {
            "A1": "G",
    (...)

この JSON 文字列の「データ」セクションをカスタム キー (「アルファベット」) で並べ替えたいと思います。上記の場合site, A1, A5, A10、実際には次のようになります。

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

並べ替え FAQでカスタム並べ替えについて読みましたが、比較関数をオーバーライドする方法を提供するだけであり、これをコードに挿入する方法がわからないことは言うまでもありません。

どうやってするか?

4

3 に答える 3

29

Python dict は順序付けされていないコレクションであるため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=(',', ': '))

プリント:

{
    "data": [
        {
            "site": "example1.com",
            "A1": "G",
            "A5": "G",
            "A10": "G"
        },
        {
            "site": "example2.com",
            "A1": "G",
            "A5": "R",
            "A10": "Y"
        }
    ],
    "Author": "joe"
}
于 2013-09-18T11:48:24.293 に答える
16

Python3 では、alecxe の回答が機能しなくなりました。これはコメントのはずですが、私には評判がありません。

PEP 3113は関数シグネチャのタプルアンパックを削除したため、次の行

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

今でなければならない

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

または類似。iteritemsもジャストになっていitemsます。

于 2016-06-29T19:03:27.600 に答える
6

私はまったく同じ問題を抱えていて、軽量の一般的な解決策を考案しました:

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

まず、カスタム オーダーの並べ替え関数のインスタンスを作成します。

custom_sort = make_custom_sort([ ["site", "A1", "A5", "A10"] ])

さて、実際の並べ替え:

result = custom_sort(allsites)

... JSON オブジェクトとしてダンプできます:

print json.dumps(result, indent=4)

結果

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

もっと

クロージャーは再帰的です。二重括弧で示されているように、構造内にネストされたさまざまな辞書が必要とする数の並べ替え順序を指定できます。

GitHub のプロジェクト: https://github.com/laowantong/customsort

于 2014-07-29T15:48:40.263 に答える