Rubyのmapとcollectは同じ?違いや戻り値の扱いを初心者向けに徹底解説
生徒
「Rubyの配列を勉強していたら、mapとcollectという二つの命令が出てきました。これらは何が違うのでしょうか?」
先生
「実は、Rubyにおいてmapとcollectは全く同じ機能を持っています。名前が二つあるだけなんですよ。」
生徒
「全く同じなんですね!でも、どうして二つも名前があるんですか?どちらを使えばいいか迷ってしまいます。」
先生
「それはプログラミングの歴史や、読みやすさが関係しています。戻り値の仕組みと一緒に、詳しく見ていきましょう!」
1. mapとcollectの正体とは?
Rubyというプログラミング言語を学んでいると、同じ動作をするのに名前が違う命令に出会うことがあります。これを専門用語でエイリアス(別名)と呼びます。map(マップ)とcollect(コレクト)は、まさにその代表例です。
この二つの命令(メソッド)の役割を一言で言うと、「配列の中身を一つずつ加工して、新しい配列を作り直す」というものです。例えば、数字が入ったリストの全てを2倍にしたり、名前に「さん」を付け加えたりするときに使います。初心者の方は、まず「どちらを使ってもコンピュータは同じように動いてくれる」ということを覚えておきましょう。
2. 戻り値という重要な考え方
プログラミング未経験の方が最初につまずきやすい言葉が戻り値(もどりち)です。これは、コンピュータに何か命令を出したときに、その結果として返ってくる「お返し」のことだと思ってください。
例えば、あなたがお店で「リンゴ」を渡して「ジュースにしてください」と頼んだとします。このとき、「ジュース」が戻り値になります。mapやcollectの場合、元の配列を加工した「新しい配列」が戻り値として返ってきます。元の配列はそのまま残るという点が非常に重要です。これを理解するために、次のコードを見てみましょう。
numbers = [1, 2, 3, 4, 5]
# 全ての数字を10倍にして新しい配列を作る
new_numbers = numbers.map do |n|
n * 10
end
puts "元の配列: #{numbers}"
puts "新しい配列: #{new_numbers}"
実行結果は以下のようになります。
元の配列: [1, 2, 3, 4, 5]
新しい配列: [10, 20, 30, 40, 50]
このように、元のnumbersという箱の中身は変わらず、新しく加工されたnew_numbersという箱が出来上がります。これがmapとcollectの大きな特徴です。
3. どちらを使うべき?可読性の観点
「全く同じなら、どちらを使えばいいの?」という疑問が湧きますよね。結論から言うと、現在のRuby開発の現場ではmapの方が圧倒的に多く使われています。
理由は単純で、名前が短くて書きやすいこと、そして数学や他のプログラミング言語でも「対応付ける」という意味でmapという言葉が一般的に使われているからです。プログラムの読みやすさを可読性(かどくせい)と言いますが、多くの人が使い慣れている言葉を選ぶことで、他の人があなたのプログラムを見たときに「ああ、ここでデータを加工しているんだな」とすぐに理解してもらえます。迷ったらmapを使う、と決めてしまっても良いでしょう。
4. collectが選ばれる理由と歴史
では、なぜcollectという名前も残っているのでしょうか。それは、Rubyが「人間にとって書きやすく、読みやすいこと」を大切にしている言語だからです。collectには「集める」という意味があります。配列の要素を加工して集める、というイメージがしっくりくる人にとっては、こちらの方が自然に感じられるのです。
また、Rubyの元になった古いプログラミング言語(Smalltalkなど)では、この処理をcollectと呼んでいました。その名残があるため、歴史を知るプログラマーの中には好んで使う人もいます。しかし、現代のトレンドとしては、やはりmapが主流です。初心者の皆さんは、もし他人の書いたコードにcollectが出てきても、「これはmapと同じ意味なんだな」と落ち着いて判断できれば完璧です。
5. 文字列の加工で使い方をマスターしよう
数字だけでなく、文字(文字列)に対しても同じように使うことができます。例えば、名前のリスト全員に「様」を付ける処理を考えてみましょう。こうした一括作業こそ、プログラムが得意とする分野です。
names = ["田中", "佐藤", "鈴木"]
# 名前を加工して挨拶のリストを作る
messages = names.collect do |name|
name + "様、こんにちは!"
end
puts messages
実行結果は以下のようになります。
田中様、こんにちは!
佐藤様、こんにちは!
鈴木様、こんにちは!
この例ではcollectを使ってみましたが、mapに書き換えても全く同じ動きをします。配列の中身が一人ずつnameという変数に取り出され、後ろに文字がくっついて、新しい配列として保存されています。手作業で一人ずつ書き換える手間が省けるので、とても便利ですね。
6. eachとの決定的な違いを理解する
似たような命令にeachというものがありますが、初心者の方はここでよく混乱します。eachは「ただ繰り返すだけ」で、加工した結果を新しい配列として返してくれる機能はありません。
料理に例えると、eachは「冷蔵庫の野菜を一つずつ眺めるだけ」ですが、mapやcollectは「野菜を一つずつ切って、お皿に乗せて、新しいサラダの盛り合わせを作る」というイメージです。新しい結果を保存したいときはmap、単に画面に表示するだけならeachと使い分けましょう。
prices = [100, 200, 300]
# mapは消費税を加えた新しい配列を作る
tax_included = prices.map do |price|
(price * 1.1).to_i
end
# eachはただ表示するだけ
prices.each do |price|
puts "元の価格は#{price}円です"
end
puts "税込み価格のリストは#{tax_included}です"
実行結果は以下のようになります。
元の価格は100円です
元の価格は200円です
元の価格は300円です
税込み価格のリストは[110, 220, 330]です
このコードにあるto_iは「整数(小数なしの数字)に変換する」という命令です。こうした細かい加工を加えながら、新しいリストを作れるのがmapとcollectの強みです。
7. ブロックの書き方を覚えよう
mapやcollectの後に続くdoからendまでの塊を、プログラミングではブロックと呼びます。このブロックの中に「どんな加工をしたいか」という指示を書きます。
また、もっと短く書く方法もあります。波括弧{ }を使う方法です。短い処理であれば、一行でスッキリ書くことができるので、慣れてきたらこちらの書き方も使ってみてください。どちらの書き方をしても、コンピュータにとっては同じ命令になります。
words = ["ruby", "java", "python"]
# 全てを大文字に変換する(短い書き方)
upcased_words = words.map { |word| word.upcase }
puts upcased_words
実行結果は以下のようになります。
RUBY
JAVA
PYTHON
upcaseは「アルファベットを大文字にする」というRubyの命令です。このように、配列の中身を一つずつ取り出して特定の命令を実行し、その結果を集めるのが基本の流れとなります。
8. map!やcollect!という「びっくりマーク」付きの命令
最後に、少しだけ応用編を紹介します。map!やcollect!のように、名前の最後に「!」が付くことがあります。これを破壊的メソッド(はかいてきめそっど)と呼びます。物騒な名前ですが、要するに「元の配列そのものを書き換えてしまう」という意味です。
通常、mapは新しい配列を作って元の配列は残しますが、「!」を付けると元の配列が上書きされます。メモリというコンピュータの記憶容量を節約するために使われることがありますが、初心者のうちは元のデータが消えてしまわないよう、まずは「!」なしの通常のmapを使うことをおすすめします。
もしプログラムが動かなくなったり、データが消えてしまったりしたときは、この「!」を誤って使っていないか確認してみてください。こうした細かい記号一つで動作が変わるのも、プログラミングの面白さであり、難しいところでもあります。