LoginSignup
2
3

More than 5 years have passed since last update.

オブジェクトの属性の追加・削除などの設定変更が多い場合に任意の属性をキーにして並び替える方法

Last updated at Posted at 2017-05-18

完全に自分向けのメモ(と戒め)

5/20 shiracamusさんからのコメントを受けて内容を修正しました。

目的

様々な属性を持つPythonのオブジェクトを
任意の属性を使って並び替えを行う方法を整理します。

想定される使いどころ

ソート対象となるクラスの属性のうち、どの属性をキーとして
ソートするかが不明な場合に利用すると良さそうです。

e.g.
webアプリ上で検索等を行う際に任意のキーを使ってソート順を指定できる場合など

また、クラスの属性の追加が頻繁に行われている場合など
にも活用が可能です。
   

概要

  1. hasattrで対象となるソートのキーに用いる属性が存在するかを確認
  2. ソートのキーとなる属性が存在する場合はソートを行う

サンプルコードと解説

サンプルコード

サンプルコード

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となった場合には、
ロガーを使ってソート処理を実施していない旨などを、
明示した方が良いかもしれません。

2
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3