1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pythonで自作クラスの大小判定(ソート)を行う

Posted at

やりたかったこと

pythonで簡単なクラスを定義して,そのクラスの中のある変数を基準にしてインスタンスが入っているリストのソートを行いたかったです.

どうやるんだっけ?となったのでやり方をメモしておきます.

作成したクラス

class Node:  # 木のノードを表すクラス
    def __init__(self, value: int, left = None, right = None):
        self.value: int = value  # ソートの基準としたい値
        self.left = left  # 左の子ノード
        self.right = right  # 右の子ノード

このクラスのvalueというint型の変数をもとに大小判定をしてリストをソートしたいです.

ソートするためにこのクラスのインスタンスのリストを適当に作成しておきます.

> import numpy as np
> nodes = [Node(np.random.randint(10)) for i in range(10)]
> print([node.value for node in nodes])
[6, 1, 7, 9, 8, 6, 4, 9, 6, 7]

このnodesというリストを単純にソートしてみると...

> sorted(nodes)
TypeError: '<' not supported between instances of 'Node' and 'Node'

このようにTypeErrorがでてソートすることができません.

Nodeインスタンス間の比較演算<がサポートされていないというエラーがでています.

やり方1: クラスに__lt__メソッドを定義する

class Node:  # 木のノードを表すクラス
    def __init__(self, value: int, left = None, right = None):
        self.left = left  # 左の子ノード
        self.right = right  # 右の子ノード
        self.value: int = value  # ソートの基準としたい値

    def __lt__(self, other):  # 自作クラスで大小を判別するための関数
        return self.value < other.value

上記のように__lt__メソッド(less than)を定義します.

引数にはselfotherを受け取ります.
self.valueother.valueより小さい時にはTrueをそうで無い時はFalseを返すようにします.

このように定義することでインスタンス間の大小を比較できるようになります.
(そのほかにも__eq__(equal)や__gt__(greater than)などの比較演算を定義できますが,ソートなら__lt__を定義しておけば十分でした.)

実際にソートしてみると...

> sorted_nodes = sorted(nodes)
> print([node.value for node in sorted_nodes])
[1, 4, 6, 6, 6, 7, 7, 8, 9, 9]

正しくソートされていました!

やり方2: ソート時に比較する際のキーを渡す

pythonのsorted関数ではオプション引数としてkeyを渡すことができます.
このkeyを渡すとこれを基準にソートを行なってくれます.

次のようにlambda式を使って書けます.

> sorted_nodes = sorted(nodes, key=lambda x: x.value)
> print([node.value for node in sorted_nodes])
[1, 4, 6, 6, 6, 7, 7, 8, 9, 9]

こちらも正しくソートされていました.

まとめ

上記2つのやり方どちらでもソートを行うことができます.

単純にソートをしたいだけならやり方2の方が早く書けると思います.

ただ優先度付きキューなどに入れたい場合やり方1を用いないとできないと思います.

参考

Python 独自クラスで比較演算ができるようにする

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?