Rubyでは「条件に合うものを抽出する」関数がfilterではなくselectだったので


最近PythonとかJavaScriptとかも触ってるんですが、コレクション(要素の集合体を扱う)ストリーム式で扱うときに「要素を特定の条件でフィルタリングする」メソッドの名称は、「filter」なんですよね。

ですが、Rubyだと該当するメソッドはselectです。小さな落とし穴ですね。

どうするか

そこでクラスを拡張し、filterを生やしてみましょう。挙動時代はselectのエイリアスです。

selectを実装しているのはEnumableモジュールです。

ですので、Enumableモジュールを拡張していることによって、これをMixinするすべてのクラス(Array,Hash,Set…)にfilter関数を生やすことが出来ます。

module Enumerable
  alias filter select
end

Railsなら、このファイルをconfig/initializersに配置しておくと、Railsのコードでfilterが使えるようになります。

実行

[1,2,3,4,5].select {|i| i.odd?} # -> [1,3,5]
['a','ab','c'].filter {|str| str.include?('a')} #->["a","ab"]

あくまでselectのエイリアスなので、selectと同じ挙動を示しますね。

最後に

Rubyのクラスはオープンクラスであり、後から別ファイルからでもクラスの持つ性質(本記事では、本来持っていなかったfilterメソッドをもたせました)を変えることができてしまいます。

これは非常に便利である一方、使い方を間違えるとコードを追うのが非常に難しくなったりする(黒魔術、と呼ばれるものの一種です)ので、いたずらに既存のクラスを開いていじくり回すのはやめましょう。

Rubyは君を信頼する。Rubyは君を分別のあるプログラマとして扱う。 Rubyはメタプログラミングのような強力な力を与える。 ただし、大いなる力には、大いなる責任が伴うことを忘れてはいけない」. -「メタプログラミングRuby」序文より