バートリーのさいとうです。
今回は
【Ruby】distinctメソッドで、結局残るのオブジェクトはどれ?が意外とわからなかったので、distinctの仕組みと共に解説
というテーマで、普段の業務から得られた学びを共有したいと思います。
Rubyには、重複を排除するために、distinctメソッドが存在します。
※uniqメソッドもありますが、Rails5から利用が非推奨になっているので、この記事では取り扱いません。
今回は、このdistinctメソッドを利用したときに、「並び順などを考えたときに、どのオブジェクトが残るのかがわかっていたい人」向けの記事となります。
要は、どのオブジェクトが排除されるんですか?ということに答えるということです。
この記事を読めば
- distinctで残る値を理解することで、その後の処理の順番など明確に理解できるようになる
- データをdistinctメソッドを通してどのように処理しているのかを理解でき、他のメソッドの理解にもつながる
と思いますので、重複排除したはいいものの、どれが残るんですか…という疑問を抱いている方は、ぜひ最後までお読みください。
distinctメソッドで残るオブジェクト
早速結論です。
distinctメソッドで残るオブジェクトは
重複する値の中で、一番初めに取得される値
です。
実例を見ていきましょう。
実例
今回は、齋藤、田中、鈴木の三人のユーザー情報が保存されているUserモデルから値を取得します。
ここに、もう1人、id=1の齋藤さんと同じ情報を持つユーザーを加えます。
User.create(name: "齋藤", age: 20)
これで、以下のようになります。
このusersテーブルから、nameカラムの値を重複を省いて、idとnameカラムの値をActiveRecordで取得します。
User.select(id:, name).distinct(:name)
=> #<ActiveRecord::Relation [ # 返り値
#<User id: 1, name: "齋藤", age: nil>,
#<User id: 2, name: "鈴木", age: nil>,
#<User id: 3, name: "田中", age: nil>,
]>
取得されたidを見ると、後から追加した4ではなく、1の方が残っていることがわかります。
id=1→2→3→4と順番で取得され、1と4のnameが重複していたので、先に取得されていた1が残った、ということですね。
なぜ上記の順番で取得されるかというと、デフォルトの取得順がASC=昇順になっているためです。
これを先に並び替えて、DESC=降順にすると、逆の現象が起きると思います。
※なお、distinctメソッドを利用してActiveRecordのオブジェクトを取得する際は、selectメソッドと一緒に使う必要があります。詳しくはこちらの記事をご覧下さい。
補足:データ取得について
補足的に、データの処理の流れについて簡単に触れます。
覚えることは一つだけで、プログラムは何も指定しない限り、昇順で値を取得します。
なので、先程の例でもあったように、数値であれば1が最初に取得されます。
これは、SQLを叩くときには必須の知識ですので、改めて強調しておきたいと思います。
まとめ
今回は、【Ruby】distinctメソッドで、結局残るのオブジェクトはどれ?が意外とわからなかったので、distinctの仕組みと共に解説というテーマで解説しました。
意外と「これを残したいんだ!」と思うタイミングがあると思うので、知っておくと便利ですね。
このブログは、月に15本を目標に、実務から学んだプログラミングのあれこれを発信しています。
誰かのためになれば、嬉しいです。
最後まで読んでいただき、ありがとうございました。
それでは。
参考記事: