RubyでEnumerableを条件Xを満たすものと満たさないものに排他的に分けたいんだけど
どうするのがいいんでしょうか。
メモリとかパフォーマンスとかそういうのはあんまり気にしない前提です。
以下のサンプルコードでは対象の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
結論
リファレンス見ろ