map で配列を変換しよう

配列の各要素に処理を適用して、新しい配列を作る方法を学びます。

.map メソッドとは

.map メソッドは、配列の各要素に処理を適用して、新しい配列を作るためのメソッドです。

numbers = [1, 2, 3] doubled = numbers.map do |num| num * 2 end p doubled # => [2, 4, 6]

この例では、numbers 配列の各要素を2倍にした新しい配列 [2, 4, 6] が作られています。

メソッドの戻り値のレッスンで学んだように、Ruby では最後に評価された式が自動的に戻り値になります.map のブロックでも同様で、num * 2 が各要素に対するブロックの戻り値となり、それらが集められて新しい配列になります。

ブロックの復習

.map メソッドは、each メソッドと同じようにブロックを使います。do...end{} で囲んだ部分がブロックです。

配列.map do |変数| 処理 end

1行で書ける短い処理には、ブレース記法も使えます。

numbers = [1, 2, 3] doubled = numbers.map { |num| num * 2 } p doubled # => [2, 4, 6]

.map と .each の違い

.each.map はどちらも配列の各要素を順番に処理しますが、戻り値が異なります

  • .each は元の配列をそのまま返す(処理の結果は返さない)
  • .map はブロックの戻り値を集めた新しい配列を返す

次の例で違いを確認してみましょう。

numbers = [1, 2, 3] # each の場合 result_each = numbers.each { |num| num * 2 } p result_each # => [1, 2, 3](元の配列がそのまま返る) # map の場合 result_map = numbers.map { |num| num * 2 } p result_map # => [2, 4, 6](処理結果の新しい配列)

.each は繰り返し処理を行いたいとき、.map は配列を変換して新しい配列を作りたいときに使います。

.map の活用例

.map は配列の変換に幅広く使えます。

文字列の配列を変換する

words = ["hello", "world"] upper_words = words.map { |word| word.upcase } p upper_words # => ["HELLO", "WORLD"]

数値を文字列に変換する

numbers = [1, 2, 3] strings = numbers.map { |num| num.to_s } p strings # => ["1", "2", "3"]

破壊的メソッド .map!

.map は元の配列を変更せず、新しい配列を返します。一方、.map!元の配列自体を変更します。このように元のデータを直接変更するメソッドを破壊的メソッドと呼びます。

numbers = [1, 2, 3] # map は元の配列を変更しない doubled = numbers.map { |num| num * 2 } p doubled # => [2, 4, 6] p numbers # => [1, 2, 3](元のまま) # map! は元の配列を変更する numbers.map! { |num| num * 2 } p numbers # => [2, 4, 6](変更された)

Ruby では、破壊的メソッドの末尾に ! をつける慣習があります。ただし、すべての破壊的メソッドに ! がついているわけではないため、使う前にドキュメントで確認するとよいでしょう。

シンボルを使った簡潔な書き方

ブロック内で各要素に対して引数なしのメソッドを1つだけ呼び出す場合、&:メソッド名 という省略記法が使えます。

words = ["hello", "world"] # 通常の書き方 upper_words = words.map { |word| word.upcase } p upper_words # => ["HELLO", "WORLD"] # 省略記法 upper_words = words.map(&:upcase) p upper_words # => ["HELLO", "WORLD"]

どちらも同じ結果になりますが、&:upcase の方が簡潔に書けます。

さまざまなメソッドで使う

この省略記法はさまざまなメソッドで使えます。

# 数値を文字列に変換 numbers = [1, 2, 3] strings = numbers.map(&:to_s) p strings # => ["1", "2", "3"] # 前後の空白を除去 words = [" hello ", " world "] trimmed = words.map(&:strip) p trimmed # => ["hello", "world"]

&:メソッド名.map 以外のメソッド(.each.select など)でも使えます。

まとめ

  • .map メソッドは各要素に処理を適用して新しい配列を作る
  • .each は元の配列を返すが、.map は変換結果の新しい配列を返す
  • .map! は元の配列自体を変更する破壊的メソッド
  • &:メソッド名 で引数なしメソッドの呼び出しを簡潔に書ける