Rubyで配列に対して繰り返しの処理を行う時は、まずeachを使っていたのですが
mapやcollectについてもきちんと勉強し、使いこなせるようにしようと思い
色々試してみました。
mapメソッドとは
array.map { |item| block }
map
メソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。
うーん、、説明だけ読むといまいちよく分からないんだよなぁ。
そして、このリファレンスに載っているサンプルコードも
いまいち分かりづらいw(16進数?)
最終的に整理がついたのですが、
- 配列に対して使う
- 配列の中身一つずつに同じ処理をし、新しい値でまた配列をつくる
みたいなイメージだと分かりやすいかな。
自前のサンプルコードと解説
この場合、結果は[3, 4, 5, 6, 7]になります。
mapメソッドは配列に対して使用するもので、
配列の中身の要素一つ一つに、指定の処理を実行していき、
その結果で新たな配列をつくる、というものです
ここでは、配列[1, 2, 3, 4, 5]の中身の要素を引数|num|に一つずつ代入し、
numに対して同じ処理(num + 2) を行っています
それを要素の数の分繰り返し、
出来上がった新しい配列をarrayに代入しています
2を足した数字で新しく配列が作られるので、
[3, 4, 5, 6, 7]という結果になる、ということです
ちなみにここでいうnum + 2はリファレンスの説明内で言う
「ブロック」に当たります。
ブロックの別の書き方
mapやcollectメソッドに限らず、
Rubyでは別のブロックの記述方法があります。
以下の2種類の書き方は同じ結果を返します。
eachで書いてみる
配列の結果を期待する時は
each文で冗長に書かずに、mapを使用すべきですね。
collectで書いてみる
collectの場合、mapメソッドと同じ書き方で同じ結果を得ることができます。
リファレンスにはこのように定義されています
collect
メソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。ブロック引数には各要素が入ります。
map
メソッドはcollect
メソッドの別名です。
mapとcollectの違い
書き方も同じで結果も同じメソッドがなぜ2つ存在するんだ・・・!
と思って違いを調べたところ、すごく分かりやすい図を見つけました
概念的な部分で違いがある様子。
- mapメソッドは配列の形を維持したまま中の要素に対し処理を行う
- collectメソッドは配列を一旦バラし、一つずつの要素に対し処理を行ったあと 再度集めて配列にする
この解釈でいくと、最初に私が説明したイメージは
どちらかというとcollectメソッドに近いのかもしれないです。。
2019/9/7追記
Railsチュートリアルをやっていたところ
こういう省略形で表現されることもある、というのを知りました
>> %w[A B C].map { |char| char.downcase } => ["a", "b", "c"] >> %w[A B C].map(&:downcase) => ["a", "b", "c"]
ブロック内の引数に対してある処理を行う場合
わざわざ二回、同じ引数を書くのが面倒なので
&:で表現することが多いらしい。
その場合、ブロックが{}ではなくなり
単純にmapの引数として(&:downcase)が登場する感じなんだな。
確かにこっちの方が簡潔で分かりやすいかも〜
ただ、downcaseメソッドをシンボルで表現している形なので
メソッド以外の処理を行う場合は使えなさそう。(べき乗とか)
Ruby on Rails チュートリアル:実例を使って Rails を学ぼう