【 Ruby】keep_ifってどんなメソッド?

Rubyにおけるメソッドへの理解を深めるために、これでもか!というくらいわかりやすく解説していくことにしました。

今回取り扱うメソッドは、「keep_if」メソッド。Railsガイド:Rubyの基礎知識を読んでいて出会ったメソッドです。

keep_ifとは、配列から、条件を満たさない要素を削除するメソッド

  • 動作条件:Ruby1.9以降

構文:配列.keep_if {|arr| 条件式 }

  • |arr|の名前はなんでもいいけど、わかりやすい名前の方がいい。(itemの”i”など)
# 処理:配列の中に"co"からはじまる要素以外を削除
pry(main)> ["cat", "cooktail", "can", "coffee", "Dog"].keep_if {|i| i =~ /^co/ }

# 実行結果
=> ["cooktail", "coffee"]

条件式部分を解説

{|i| i =~ /^co/ }

“=~”

  • 正規表現のメソッドの一つ。後述する正規表現と文字列がマッチさせる。今回の場合、配列と”/^co/”を比較しており、文字列にあたるのが配列で、正規表現にあたるのが”/^co/”。

“^co”

  • “^”は文字列の先頭を表す正規表現。今回の場合、「”co”からはじまる文字」という意味になる。

“https://”

  • 囲まれた部分が正規表現であることを表す記号。

実行結果解説

「”co”からはじまる」という条件式がtrueになるのは”coffee”と”cooktail”のみ。それ以外の「”cat”, “can”, “Dog”」はfalseになるので削除される。

ちなみに、rubyの正規表現ではデフォルトだと大文字と小文字を区別するので注意。ただし、”i”オプションをつけると大文字と小文字を区別しなくなる

iオプションなし

# 処理
pry(main)> ["cat", "cooktail", "can", "coffee", "Dog"].keep_if {|v| v =~ /^d/ }

# 実行結果:小文字の"d"からはじまる文字列は配列の中にない
=> []
# 処理 
pry(main)> ["cat", "cooktail", "can", "coffee", "Dog"].keep_if {|v| v =~ /^D/ }

# 実行結果: 大文字の"D"からはじまる文字列は配列の中に"Dog"が該当する
=> ["Dog"]

iオプションあり

# 処理
pry(main)> ["cat", "cooktail", "can", "coffee", "Dog"].keep_if {|v| v =~ /^d/i }

# 実行結果
=> ["Dog"]
  • “/^d/”で小文字の”d”からはじまる文字列を指定しているが、iオプションがあるので大文字・小文字を区別せずに”Dog”が返って来る。

keep_ifを使う上で一番気をつけるべきポイント

破壊的メソッドである
便利ですが、破壊的メソッドなので使いどころには注意が必要です。
keep_ifで配列を掃除する

破壊的メソッドとは、 メソッドの実行結果で元の配列やハッシュの内容を上書きするメソッドのこと。

# groupsに配列にした要素を代入
pry(main)> groups = ["cat", "cooktail", "can", "coffee", "Dog"]

# keep_ifメソッドで"CA"を含む要素以外を削除
groups.keep_if {|group| group =~ /CA/i }

# 実行結果
["cat", "can"]

# pメソッドでgroups変数を出力
["cat", "can"]

元々、groups変数には、["cat", "cooktail", "can", "coffee", "Dog"]が代入されていましたよね。

でも、keep_ifメソッドは破壊的メソッドなんで、実行結果で配列内の要素が上書きされてしまいます。

groups変数を出力すると、["cat", "can"]だけになってしまったことがわかります。

最後に

わからないことを自分が理解できるまで噛み砕いて解説すると理解が深まりますね。

この記事をシリーズ化して、自分だけのリファレンスを作ろうかな。

参考サイト

「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典-正規表現 (regular expression)-

Rubyリファレンス-keep_if (Array)-