完全に自分向けのメモ(と戒め)
5/20 shiracamusさんからのコメントを受けて内容を修正しました。
目的
様々な属性を持つPythonのオブジェクトを
任意の属性を使って並び替えを行う方法を整理します。
想定される使いどころ
ソート対象となるクラスの属性のうち、どの属性をキーとして
ソートするかが不明な場合に利用すると良さそうです。
e.g.
webアプリ上で検索等を行う際に任意のキーを使ってソート順を指定できる場合など
また、クラスの属性の追加が頻繁に行われている場合など
にも活用が可能です。
概要
- hasattrで対象となるソートのキーに用いる属性が存在するかを確認
- ソートのキーとなる属性が存在する場合はソートを行う
サンプルコードと解説
サンプルコード
サンプルコード
class SampleClass(object):
"""
ソート対象となるサンプルクラス
"""
def __init__(self, value1, value2):
self.value1 = value1
self.value2 = value2
def __str__(self):
return str(self.value1) + "," + str(self.value2)
def sort(objs, sort_rule=("value1", "asc")):
"""
ソート用の関数
"""
key, order = sort_rule
is_reverse = (order.lower() != "asc")
if hasattr(objs[0], key):
return sorted(objs, key=lambda obj: getattr(obj, key), reverse=is_reverse)
return objs
targets = [
SampleClass(value1="test003", value2="sample003"),
SampleClass(value1="test002", value2="sample001"),
SampleClass(value1="test001", value2="sample002")
]
# value1をキーにして並び替え
sorted_targets = sort(objs=targets)
for obj in sorted_targets:
print(obj)
print("========")
# value2をキーにして、降順で並び替え
# dscを指定しているけれども、実際にはasc以外ならなんでも良い
sorted_targets = sort(objs=targets, sort_rule=("value2", "dsc"))
for obj in sorted_targets:
print(obj)
実行結果
test001,sample002
test002,sample001
test003,sample003
========
test003,sample003
test001,sample002
test002,sample001
解説
ソートのメソッド
def sort(objs, sort_rule=("value1", "asc")):
"""
ソート用の関数
"""
key, order = sort_rule
is_reverse = (order.lower() != "asc")
if hasattr(objs[0], key):
return sorted(objs, key=lambda obj: getattr(obj, key), reverse=is_reverse)
return objs
objsは、並び替えの対象となるリストを含みます。
sort_ruleにはtupleで対象となるキーと昇順(asc)、
または降順(dsc、コード上は任意文字列も可)を指定します。
注意点
hasattrで対象とする属性の有無を判断していますが、
配列に含まれるオブジェクト全てが同じ属性を持っている前提となっているので
その点は注意が必要です。
また、hasattrを使った判定の際にfalseとなった場合には、
ロガーを使ってソート処理を実施していない旨などを、
明示した方が良いかもしれません。