Pythonで辞書型のネスト部分でソートしたい

辞書型はネストが深くなるとソート方法がわからなくなるので、まとめておきます。

ネストされた辞書型のサンプルデータを作成します。

import json

data = {
    'Ken' : { 'Country': 'US', 'Job': 'Artist', 'Age': 56 },
    'Alan' : { 'Country': 'Japan', 'Job': 'Carpenter', 'Age': 27 },
    'Steven' : { 'Country': 'China', 'Job': 'Artist', 'Age': 40 }
}

print(json.dumps(data, indent=4))

このように出力されます。

{
    "Ken": {
        "Country": "US",
        "Job": "Artist",
        "Age": 56
    },
    "Alan": {
        "Country": "Japan",
        "Job": "Carpenter",
        "Age": 27
    },
    "Steven": {
        "Country": "China",
        "Job": "Artist",
        "Age": 40
    }
}

辞書型の第1階層でソート

第1階層でソートします。
つまり、サンプルデータのKen, Alan, Stevenの名前でソートします。

辞書型のソートにはkey=lambdaを使います。
第1階層のソートでは、その後にx:x[0]と書きます。

import json

data = {
    'Ken' : { 'Country': 'US', 'Job': 'Artist', 'Age': 56 },
    'Alan' : { 'Country': 'Japan', 'Job': 'Carpenter', 'Age': 27 },
    'Steven' : { 'Country': 'China', 'Job': 'Artist', 'Age': 40 }
}

# 第1階層のKEYで昇順でソートする。
data = dict(sorted(data.items(),
        key=lambda x:x[0],
        reverse=False))

print(json.dumps(data, indent=4))

第1階層のキーをアルファベット順の昇順で、Alan → Ken → Stevenと出力できています。

{
    "Alan": {
        "Country": "Japan",
        "Job": "Carpenter",
        "Age": 27
    },
    "Ken": {
        "Country": "US",
        "Job": "Artist",
        "Age": 56
    },
    "Steven": {
        "Country": "China",
        "Job": "Artist",
        "Age": 40
    }
}

辞書型の第2階層でソート

第2階層のAgeキーでソートします。

第2階層のソートでは、key=lambda x:x[1][“ソートに使うKEY”]とします。

import json

data = {
    'Ken' : { 'Country': 'US', 'Job': 'Artist', 'Age': 56 },
    'Alan' : { 'Country': 'Japan', 'Job': 'Carpenter', 'Age': 27 },
    'Steven' : { 'Country': 'China', 'Job': 'Artist', 'Age': 40 }
}

# 第2階層の"Age"キーで昇順でソートする。
data = dict(sorted(data.items(),
        key=lambda x:x[1]['Age'],
        reverse=False))

print(json.dumps(data, indent=4))

第2階層のAgeキーを昇順で、27 → 40 → 56と出力できています。

{
    "Alan": {
        "Country": "Japan",
        "Job": "Carpenter",
        "Age": 27
    },
    "Steven": {
        "Country": "China",
        "Job": "Artist",
        "Age": 40
    },
    "Ken": {
        "Country": "US",
        "Job": "Artist",
        "Age": 56
    }
}

辞書型の第2階層を複数キーでソート

第2階層の複数のキーでソートしてみます。
優先順位は “Job”, “Country” の順とします。

第2階層の複数キーのソートでは、key=lambda x:(x[1][“第1優先KEY”], x[1][“第2優先KEY”])とします。

2つ以上の複数キーでソートする場合は、さらにカンマでつなげるだけです。

import json

data = {
    'Ken' : { 'Country': 'US', 'Job': 'Artist', 'Age': 56 },
    'Alan' : { 'Country': 'Japan', 'Job': 'Carpenter', 'Age': 27 },
    'Steven' : { 'Country': 'China', 'Job': 'Artist', 'Age': 40 }
}

# 第2階層の複数キーで昇順でソートする。
data = dict(sorted(data.items(),
        key=lambda x:(x[1]['Job'], x[1]['Country']),
        reverse=False))

print(json.dumps(data, indent=4))

StevenとKenの”Job”は”Artist”なので同じですが、”Country”キーが”China”のStevenの方が上にソートできています。

{
    "Steven": {
        "Country": "China",
        "Job": "Artist",
        "Age": 40
    },
    "Ken": {
        "Country": "US",
        "Job": "Artist",
        "Age": 56
    },
    "Alan": {
        "Country": "Japan",
        "Job": "Carpenter",
        "Age": 27
    }
}

わかりにくい場合は、降順に切り替えてみる (reverse=True に変更する) と違いがわかります。

import json

data = {
    'Ken' : { 'Country': 'US', 'Job': 'Artist', 'Age': 56 },
    'Alan' : { 'Country': 'Japan', 'Job': 'Carpenter', 'Age': 27 },
    'Steven' : { 'Country': 'China', 'Job': 'Artist', 'Age': 40 }
}

# 第2階層の複数キーで降順でソートする。
data = dict(sorted(data.items(),
        key=lambda x:(x[1]['Job'], x[1]['Country']),
        reverse=True))

print(json.dumps(data, indent=4))
{
    "Alan": {
        "Country": "Japan",
        "Job": "Carpenter",
        "Age": 27
    },
    "Ken": {
        "Country": "US",
        "Job": "Artist",
        "Age": 56
    },
    "Steven": {
        "Country": "China",
        "Job": "Artist",
        "Age": 40
    }
}