Code Fix

初級

each は配列を変換しない(map との違い)

eachブロックの中で要素を加工しても、eachの戻り値はレシーバ自身(変更前の配列)のままです。加工した結果からなる新しい配列が欲しい場合はmapを使う必要があります。

なぜエラーが出ないのか

出力: [1, 2, 3]
(エラーなし)
Rubyは何も報告しません。文法として正しいためです
出力: [1, 2, 3]
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  nums = [1, 2, 3]
 2  doubled = nums.each { |n| n * 2 }
                     ^
 3  puts doubled.inspect
出力: [1, 2, 3]

eachはブロックの中で何を計算しても、戻り値は常に元の配列自身です。変換結果の配列が欲しい場合はmapを使います。

直し方: eachmap にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  prices = [100, 200, 300]
 2  taxed = prices.each { |p| (p * 1.1).round }
                     ^
 3  puts taxed.inspect
出力: [100, 200, 300]

eachブロックの中の計算結果は捨てられ、doubledには変更前の配列がそのまま入ります。

直し方: eachmap にします。

この問題を解いてみる →

パターン3

 1  names = ["taro", "hanako"]
 2  upcased = names.each { |n| n.upcase }
                      ^
 3  puts upcased.inspect
出力: ["taro", "hanako"]

文字列を大文字化した「つもり」でも、eachでは元の配列が変わらないまま返ってきます。

直し方: eachmap にします。

この問題を解いてみる →

パターン4

 1  scores = [60, 70, 80]
 2  bonused = scores.each { |s| s + 10 }
                       ^
 3  puts bonused.inspect
出力: [60, 70, 80]

加算した結果を集めた新しい配列が欲しいなら、eachをmapに置き換える必要があります。

直し方: eachmap にします。

この問題を解いてみる →

パターン5

 1  words = ["cat", "dog"]
 2  lengths = words.each { |w| w.length }
                      ^
 3  puts lengths.inspect
出力: ["cat", "dog"]

エラーは出ないため、出力を確認するまでeachとmapの取り違えには気づけません。

直し方: eachmap にします。

この問題を解いてみる →

よくある誤解

「eachブロックの中で計算した結果が、そのままeachの戻り値になるはず」という思い込みは誤りです。eachは常に元の配列自身を返すため、変換結果を集めたいならmapに置き換える必要があります。

まとめ

each は配列を変換しない(map との違い)は初級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)