読者です 読者をやめる 読者になる 読者になる

RubyでEnumerableを条件Xを満たすものと満たさないものに排他的に分けたいんだけど

技術系日記 Ruby

どうするのがいいんでしょうか。
メモリとかパフォーマンスとかそういうのはあんまり気にしない前提です。

以下のサンプルコードでは対象のEnumerableは変数 arr に代入されているものとし、条件Xを満たすかどうかのメソッドは foo?(x) という名前であるとします*1

普通に書く

a = arr.select { |e| foo?(e) }
b = arr.select { |e| !foo?(e) }

排他的に分けたいのにブロックが2回書かれている。 条件に変更があった場合の変更漏れ、うっかり ! つけ忘れるなどのミスをやりそう。微妙。

selectとrejectする

a = arr.select { |e| foo?(e) }
b = arr.reject { |e| foo?(e) }

おんなじブロックを使うからまだミスが減る気はする。が、微差だろう。

引き算する

a = arr.select { |e| foo?(e) }
b = arr - a

排他的っぽい。割とよい

まとめてみる

tmp = arr.group_by { |e| foo?(e) }
a = tmp[true]
b = tmp[false]

hash[true] がそこはかとなくキモい気がする……。

調べてみる

a, b = arr.partition { |e| foo?(e) }

普通にあった*2

参考: https://docs.ruby-lang.org/ja/latest/class/Enumerable.html#I_PARTITION

結論

リファレンス見ろ

*1:どうでもいいけどpredicate methodと聞くと毎回predict思い出してついでにエッグベネディクトまで思い出してお腹がすく

*2:ちなみに記事書き始めてから見つけた