配列を使った繰り返しの処理をRubyで作るなら、ぜひ、mapメソッドが使えないか検討してください。もちろんRubyで配列で繰り返しといったらeachを使うのが基本ですが、Rubyで使えるのはeachだけではありません。場合によっては、mapメソッドを使った方が、簡潔で見やすく、いかにもRubyらしいプログラムが書けます。今回は、Rubyらしいプログラムの書き方に興味のある方向けに、mapメソッドについて解説します。
mapメソッドとは
配列を使った繰り返し処理をプログラミングするなら、forやforeachといった機能を使うのが一般的です。そして、Rubyではeachメソッドを使うのが一般的と言えるでしょう。しかし、場合によっては、eachメソッドの代わりに他のメソッドも使えるのをご存じでしょうか。
次から、eachメソッドを使うよりも見やすく簡単に繰り返し処理が書ける、mapメソッドについてご紹介します。
rubyでループを作る方法の一つ
プログラミングを組む際、繰り返し処理を作って、その中で何をやるかが重要です。そのため、ほぼ全てのプログラミング言語に、繰り返し処理を作るための機能が用意されています。もちろんRubyも例外ではありません。
なお、Rubyでループを組む際に使える機能は、while文、for文、eachメソッド、timesメソッドなど複数あり、場合によって使い分けるのが正しい使い方です。そして、もし、配列を使って繰り返し処理のプログラムを作るのならRubyではeachを使うのが一般的と言えるでしょう。
しかし、Rubyで配列を使って繰り返し処理を実現できるメソッドは、eachだけではありません。Rubyにはmapやselectなど、配列で使えるいろいろなメソッドが用意されています。中でもmapは、配列内のデータをまとめて加工できることから、利用頻度の高いメソッドを言えます。もし、eachメソッドだけでプログラムを書いているのなら、mapメソッドを使ってみてはいかがでしょうか。
ループを実現するmapメソッドの書き方
先ほども紹介したように、mapメソッドは、配列の各要素に対して同じ処理を適用したいときに使用します。もちろん、同じ処理をeachでも書けますが、mapメソッドを使うことで、適用したい処理をシンプルに記述できるのがメリットと言えます。
なお、今回紹介するmapメソッドは、Enumerableモジュールに含まれています。そのため、whileやforなどと違い、Rubyの制御構造ではないため、Rubyのインストール方法によっては使えないケースもありますが、普通にインストールされたRubyなら大抵利用できます。
そして、mapメソッドの使い方ですが、処理結果を指定した変数に代入させるのが基本です。また、mapの末尾に「!」を付けたmap!メソッドを使用することで元のデータを変更する処理を記述できます。
#{}を使ったmapメソッドの例 dlist = [1, 2, 3] olist = dlist.map { |n| n * 3 } p olist # [3, 6, 9]
なお、上の例ではmapメソッドの処理を{}で囲んでいますが、do end で囲んでも同じです。
#do endを使ったmapメソッドの例 dlist = [1, 2, 3] olist = dlist.map do |n| n * 3 end p olist # [3, 6, 9]
- ループに{}を使う:配列.map { |変数| 処理 }
- ループにdo end を使う:配列.map do |変数| 処理 end
mapメソッドの使い方
mapメソッドの使い方について、同じ配列で繰り返し処理でよく使われるeachと比較しながら解説します。
配列に対して適用するメソッド
Rubyのプログラムに限らず、配列に対して繰り返し処理を実施する場合、一旦、何かの変数にコピーして、その変数を加工するのが一般的です。Rubyでも、eachメソッドで書く場合は、そのように記述します。
しかし、mapメソッドを使うと、配列の全てに同じ処理を適用することになるので、変数にコピーする必要はありません。それだけシンプルに書けるということですから、よりRubyらしい書き方ができるメソッドと言えます。
mapメソッドの書き方
では、eachメソッドの書き方とmapメソッドの書き方の違いを具体例で見てみましょう。例として、数値を格納した配列を使い、一律に2倍するループを作ってみます。
#eachメソッドを使った例 dlist = [ 10, 2, 5, 8, 3 ] olist = [] dlist.each do |val| olist << val * 2 end
そして、上のeachメソッドと同じ処理をmapメソッドで書くと次のようになります。
#mapメソッドを使った例 dlist = [ 10, 2, 5, 8, 3 ] olist = dlist.map do |val| val * 2 end
いかがでしょうか。mapメソッドを使うことで、すっきりした読みやすいプログラムが書けると思いませんか。
mapメソッドの応用
先ほどmapメソッドの具体的な使い方を紹介しましたが、他にも便利な使い方があるので、次からご紹介します。
indexが使える
配列の要素の数だけループを回すeachメソッドやmapメソッドですが、インデックス番号を使いたいケースもあるでしょう。mapメソッドに、.with_indexを追加することで、eachと同じようにインデックス番号が使えます。
例えば、要素数が同じ2つの配列の要素同士の積を求めて新しい配列を作る場合、indexを使って次のように書くことができます。
#indexを使った例 dlist = [10, 8, 6, 4, 2, 1] xlist = [ 1, 2, 3, 4, 5, 6] olist = dlist.map.with_index do |val, index| val * xlist[index] end p olist # [ 10, 16, 18, 16, 10, 6 ]
連想配列(ハッシュ)も扱える
連想配列(ハッシュ)とは、配列内の個別のデータを参照する際、数字の代わりに文字列を使う機能です。データベースから読み込んだデータを参照したり、ファイルから読み込んだデータを処理する場合など、実際のプログラムではよく使われる機能です。そして、連想配列(ハッシュ)は、若干制限はありますがRubyでも利用できます。
そして、今回紹介しているmapメソッドも、この連想配列(ハッシュ)を使った配列に対しても処理できます。ただし、その場合、配列の引数と値の両方を使って記述するので、書き方に注意してください。また、mapメソッドが生成するは配列であって連想配列(ハッシュ)ではありません。連想配列(ハッシュ)として利用するためには、後から変換する必要があります。
次に連想配列(ハッシュ)にmapメソッドを適用した簡単な例を紹介します。
#連想配列(ハッシュ)に格納された数値を2倍にした配列を作る例 hlist = { "case1" => 100, "case2" => 200, "case3" => 300 } olist = hlist.map { |key, value| [ key, value * 2] }.to_h p olist #{"case1"=> 200, "case2"=> 400, "case3"=> 600 }
#連想配列(ハッシュ)の引数を別の文字にした配列を作る例 hlist = { "name" => "ruby", "class" => "program", "type" => "script", "term" => "month" } olist = hlist.map { |key, val| [ key + "_1", val" ] }.to_h p olist #{"name_1"=>"ruby", "class_1"=>"program", "type_1"=>"script", "term_1"=>"month"}
上記の例で、mapメソッドで新たに作った配列を連想配列(ハッシュ)にするため、to_hメソッドを使っています。そして、このメソッドは、Ruby 2.1以降のバージョンでなければ動作しません。そのため、RedhatやCentOSなど、デフォルトでインストールされている古いバージョンのRubyで動作しないこともあります。
mapメソッドの省略形
配列の要素に対して、数値を文字列に変換したり、文字列の最後に付いている改行コードを削除する、といった処理で、mapメソッドはよく使われます。そういった処理では、mapメソッドの省略形が使えるので、ぜひ、活用しましょう。次からmapメソッドの省略形についてご紹介します。
mapメソッドの省略形の書き方
mapメソッドでは、「&」を使いで省略形で書くことができます。これによって、do~endブロックまたは {}の中に書かれた処理を簡単に書けるでの、より読みやすくなります。具体的には、数値を文字列に変換する処理は、下記のように書き換えることが可能です。
#変数を使ったmapメソッドの使い方 dlist = [ 1, 2, 3, 4, 5 ] olist = dlist.map do |val| val.to_s end #省略形を使ったmapメソッドの使い方 dlist = [ 1, 2, 3, 4, 5 ] olist = dlist.map(&:to_s)
なお、Rubyに限らずプログラムを作る場合、変数の扱いには注意を払う必要があります。そのため、プロジェクトによっては変数の命名規則を厳密にすることで不具合防いでいるケースもあるくらいです。その点、Rubyの「&」を使う省略形は、変数を減らせるメリットがあるのでうまく活用しましょう。
まとめ
Rubyで配列を使った繰り返しと言えばeachメソッドが定番ですが、場合によっては別のメソッドを使うことで読みやすく簡潔に書くことができます。そして、その代表が、mapメソッドです。
なお、mapメソッドは、配列の全てのデータに同じ処理を行うための機能であり、&を使った省略形なら一行で書くことも可能です。ぜひ、eachメソッドばかりではなく、mapメソッドも使ってRubyらしいプログラムを書いてください。
数値を格納した配列をまとめて文字列に変換する処理は、Ruby on Railなどでよく使われます。その際、mapメソッドの省略形を使用することで、一行で簡単に書けるので、ぜひ、利用してください。