Ruby Sliverでよく出題される。「同じ動作をするメソッドを選べ」的な問題をまとめておきます。
find_allメソッドは、条件に合う要素を探して集めます。ブロック引数itemに要素を入れながらブロックを繰り返し、ブロックの戻り値が真になったときの要素を集め、配列にして返します。 selectメソッドは、find_allの別名です。
# 1から30までの整数のうち7で割り切れるものを集めています。
# selectの場合
irb(main):001:0> p (1..30).select { |n| n % 7 == 0 }
[7, 14, 21, 28]
=> [7, 14, 21, 28]
# find_allの場合
irb(main):003:0> p (1..30).find_all { |n| n % 7 == 0 }
[7, 14, 21, 28]
=> [7, 14, 21, 28]
collectメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。ブロック引数itemには各要素が入ります。 mapメソッドはcollectメソッドの別名です。
# 16進数を表す文字列を数値に変換した配列を作成しています。
# collectの場合
irb(main):001:0> numbers = ["68", "65", "6C", "6C", "6F"]
=> ["68", "65", "6C", "6C", "6F"]
irb(main):002:0> p numbers.collect { |item| item.to_i(16) }
[104, 101, 108, 108, 111]
=> [104, 101, 108, 108, 111]
# mapの場合
irb(main):003:0> p numbers.map { |item| item.to_i(16) }
[104, 101, 108, 108, 111]
=> [104, 101, 108, 108, 111]
findメソッドは、要素を探して取り出します。ブロック引数itemに要素を入れながらブロックを繰り返し、ブロックが真が返したときは繰り返しを中断してその要素を返します。ブロックの戻り値がすべて偽であればnilを返します。 detectメソッドは、findの別名です。
# 配列の中から5で割り切れる数を探します。
# findの場合
irb(main):001:0> numbers = [15, 55, 89, 99, 121, 134]
=> [15, 55, 89, 99, 121, 134]
irb(main):002:0> numbers.find {|item| item % 5 == 0 }
=> 15
# detectの場合
irb(main):001:0> numbers = [15, 55, 89, 99, 121, 134]
=> [15, 55, 89, 99, 121, 134]
irb(main):004:0> numbers.detect {|item| item % 5 == 0 }
=> 15
delete_ifメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値が真になった要素を削除します。レシーバ自身を変更するメソッドです。ブロック引数itemには各要素が入ります。 reject!メソッドとは異なり、戻り値は常にレシーバ自身です。
reject!メソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値が真になった要素を削除します。レシーバ自身を変更するメソッドです。ブロック引数itemには各要素が入ります。 delete_ifと同じことをするメソッドですが、戻り値だけ異なります。削除が行われたときはレシーバ自身を返し、変化がなかったときはnilを返します。
# delete_ifの場合
irb(main):001:0> fruits = ["apple", "orange", "banana", "kiwi", "peach", "endoumame", "strawberry"]
=> ["apple", "orange", "banana", "kiwi", "peach", "endoumame", "strawberry"]
#先頭の文字が`aiueo`のいずれかにマッチした場合は要素を削除する
irb(main):002:0> fruits.delete_if {|item| item =~ /^[aiueo]/ }
=> ["banana", "kiwi", "peach", "strawberry"]
# reject!の場合
irb(main):001:0> fruits = ["apple", "orange", "banana", "kiwi", "peach", "endoumame", "strawberry"]
=> ["apple", "orange", "banana", "kiwi", "peach", "endoumame", "strawberry"]
#先頭の文字が`aiueo`のいずれかにマッチした場合は要素を削除する
irb(main):002:0> fruits.reject! {|item| item =~ /^[aiueo]/ }
=> ["banana", "kiwi", "peach", "strawberry"]