投稿日:2020年10月24日
Pythonでdict型の配列を並び替えをする場合、sort()関数やsorted()関数をそのまま使うことはできません。この記事ではdict型の配列の並び変えの仕方について実践を交えて細かく解説しています。
Pythonでdict型の配列を並び替えをする場合、sort()関数やsorted()関数をそのまま使うことはできません。この記事ではdict型の配列の並び変えの仕方について実践を交えて細かく解説しています。
この記事のコードは以下の環境で実行されました。
ここではサンプルとして以下のdict型の配列について考えます。
data = [
{
"name" : "藍染 惣右介",
"sex" : "male",
"height" : 205,
"weight" : 91
},
{
"name" : "更木 剣八",
"sex" : "male",
"height" : 202,
"weight" : 90
},
{
"name" : "四楓院 夜一",
"sex" : "female",
"height" : 156,
"weight" : 42
},
{
"name" : "日番谷 冬獅郎",
"sex" : "male",
"height" : 133,
"weight" : 28
},
{
"name" : "雛森 桃",
"sex" : "female",
"height" : 151,
"weight" : 39
},
]
list型にはsort()という順番を並びかえるメソッドが用意されているのですが、
これはデフォルトでは単純な大小を比較するため、
そのままではdict型の配列を処理することはできません。
data.sort()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-cfdd66cfdfb7> in <module>
----> 1 data.sort()
TypeError: '<' not supported between instances of 'dict' and 'dict'
この点はsorted()についても同様のことが言えます。
sorted(data)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-33bae22008f5> in <module>
----> 1 sorted(data)
TypeError: '<' not supported between instances of 'dict' and 'dict'
Pythonでは関数を引数に渡すことができます。
ここでは無名関数を使ってsort()関数をheigtの値ごとに並び替える関数にカスタマイズしてみます。
この様に関数の引数として関数を渡すことで、その関数の処理をカスタマイズする仕組みのことをフック(hook)と言います。
data.sort(key=lambda x: x["height"])
print(data)
[{'name': '日番谷 冬獅郎', 'sex': 'male', 'height': 133, 'weight': 28}, {'name': '雛森 桃', 'sex': 'female', 'height': 151, 'weight': 39}, {'name': '四楓院 夜一', 'sex': 'female', 'height': 156, 'weight': 42}, {'name': '更木 剣八', 'sex': 'male', 'height': 202, 'weight': 90}, {'name': '藍染 惣右介', 'sex': 'male', 'height': 205, 'weight': 91}]
hookはsorted()でも同じように渡すことができます。
少し複雑な処理などを入れたい場合などには、関数を定義してそれをhookとして渡してあげると良いでしょう。
def bmi_hook(obj):
return obj["weight"]/(obj["height"] ^ 2)
data.sort(key=bmi_hook)
print(data)
[{'name': '日番谷 冬獅郎', 'sex': 'male', 'height': 133, 'weight': 28}, {'name': '雛森 桃', 'sex': 'female', 'height': 151, 'weight': 39}, {'name': '四楓院 夜一', 'sex': 'female', 'height': 156, 'weight': 42}, {'name': '藍染 惣右介', 'sex': 'male', 'height': 205, 'weight': 91}, {'name': '更木 剣八', 'sex': 'male', 'height': 202, 'weight': 90}]
昇順・降順はhookが返す値をマイナスにする方法などもありますが、
reverse引数によっても制御することができます。
data.sort(key=lambda x: x["height"],reverse=False)
print(data) #昇順
data.sort(key=lambda x: x["height"],reverse=True)
print(data) #降順
[{'name': '日番谷 冬獅郎', 'sex': 'male', 'height': 133, 'weight': 28}, {'name': '雛森 桃', 'sex': 'female', 'height': 151, 'weight': 39}, {'name': '四楓院 夜一', 'sex': 'female', 'height': 156, 'weight': 42}, {'name': '更木 剣八', 'sex': 'male', 'height': 202, 'weight': 90}, {'name': '藍染 惣右介', 'sex': 'male', 'height': 205, 'weight': 91}]
[{'name': '藍染 惣右介', 'sex': 'male', 'height': 205, 'weight': 91}, {'name': '更木 剣八', 'sex': 'male', 'height': 202, 'weight': 90}, {'name': '四楓院 夜一', 'sex': 'female', 'height': 156, 'weight': 42}, {'name': '雛森 桃', 'sex': 'female', 'height': 151, 'weight': 39}, {'name': '日番谷 冬獅郎', 'sex': 'male', 'height': 133, 'weight': 28}]