Ruby

【Ruby】distinctメソッドで、結局残るのオブジェクトはどれ?が意外とわからなかったので、distinctの仕組みと共に解説

バートリーのさいとうです。

今回は

【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本を目標に、実務から学んだプログラミングのあれこれを発信しています。

誰かのためになれば、嬉しいです。

最後まで読んでいただき、ありがとうございました。

それでは。

参考記事:

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA