そういやmapメソッドって何だっけと、ふと疑問に思いまとめてみました。
mapメソッドとは
mapメソッドは配列の要素の数だけブロック内の処理を実行し、作成された配列を返すメソッドです。
要素それぞれに指示した処理をしてくれます。
似たようなメソッドにはeachメソッドがありますね。
eachメソッドは戻り値は元の配列、mapはブロック処理をした後の値を集めた配列を戻り値にします。
配列を元に新たな配列を作成する場合はmapメソッドを
繰り返し処理をするだけの場合はeachメソッドを使いましょう。
mapメソッドの基本的な書き方
配列.map { |変数| 実行する処理 }
# 実行する処理が複数行の場合
配列. map do |変数|
実行する処理
end
使用例
irb(main):001:0> numbers = [10, 20, 30, 40]
=> [10, 20, 30, 40]
irb(main):002:0> new_numbers= numbers.map { |n| n * 2 }
=> [20, 40, 60, 80]
irb(main):003:0> new_numbers
=> [20, 40, 60, 80]
map!メソッド
mapメソッドとは別でmap!メソッドというメソッドがあります。
mapメソッドとの違いはmapメソッドは元となった配列を変更しないのに対して、
map!メソッドは元の配列を書き換えます。破壊的メソッドと呼ばれるタイプです。
書き方はmapメソッドと同じで
mapメソッドの基本的な書き方
配列.map { |変数| 実行する処理 }
# 実行する処理が複数行の場合
配列. map do |変数|
実行する処理
end
になります。
eachメソッドとmapメソッド、map!メソッドの実行結果
numbers = [1,2,3,4,5]
puts "each"
numbers_each = numbers.each {|n| n*2}
# 返り値は元の配列なので、[1,2,3,4,5]が出力される
p numbers_each
puts "map"
numbers_map = numbers.map {|n| n*2}
# 返り値はブロック処理の結果を集めた配列なので、
# 2倍になった配列が出力される
p numbers_map
puts "map!"
numbers.map! {|n| n*2}
# 破壊的メソッドは元の配列を書き換える
p numbers
each
[1, 2, 3, 4, 5]
map
[2, 4, 6, 8, 10]
map!
[2, 4, 6, 8, 10]
注目していただきたいのはmapメソッドはnumbers_map = numbers.map {|n| n*2}
として
処理をされたものを代入して出力されているのに対して
map!メソッドは代入せずにnumbers.map! {|n| n*2}
でnumber
の値が変わっているところです。
mapメソッドの省略形
mapメソッドは3つの条件が合えばブロックを渡す代わりに&:メソッド名
を使って
省略して書くことができます。
- ブロックの引数が1つであること
- ブロックの呼び出すメソッドに引数がないこと
- ブロック引数に対して、メソッドを呼び出す以外の処理がないこと
# 通常の書き方
["RUBY", "RAILS", "VUE.JS"].map { |s| s.downcase }
=> ['ruby', 'rails', 'vue.js']
# 省略した書き方
["RUBY", "PHP", "JAVA"].map(&:downcase)
=> ["ruby", "rails", "vue.js"]
mapメソッドの応用的な使い方
データベースから特定の値だけを配列にする
mapメソッドはテーブルから特定のカラムを取り出したいときに便利です。
例えばUserテーブルからemailだけを取り出して新たに配列を作ることができます。
users = Users.all
users.map { |user| user.name }
=> ["Maria", "Jun", "Norah", "Lucas", "Sophia", "Chin", "Tom", "Taro"]
注意
紹介しておいて何なんですが、mapメソッドはテーブル全体から取り出したものを配列に返すので
このようにデータベースから特定の値だけを配列にする場合はpluckメソッドを使いましょう。
pluckメソッドはデータベースから取り出す段階で特定のカラムを取り出すため
パフォーマンスが上がります。
#####逆にpluckメソッドを使わずmapメソッドを使った方がいいとき
インスタンス化したオブジェクトからデータを取得する場合は、mapメソッドを使いましょう。
理由としては、pluckメソッドはインスタンス化したオプジェクトに対しても毎回SQLを実行してしまいパフォーマンスの低下に繋がるからです。
参考サイト
Pikawaka
TechAcademyマガジン Rubyのmap/map!メソッドの書き方を現役エンジニアが解説【初心者向け】