Paizaの問題でMath.max()
を使ったら、まさかのエラー。
「配列をそのまま渡せない」 という基本的なポイントを見落としてた…。
同じミスをしないように、サクッと整理!
問題概要
問題: A, B, C の最大値と最小値の差を求める
入力: 30 50 10
出力: 40
NG例(間違いコード)
const rl = require('readline').createInterface({ input: process.stdin });
rl.on('line', (input) => {
const nums = input.split(' ').map(Number);
console.log(Math.max(nums) - Math.min(nums)); // ここが間違い!
rl.close();
});
→ Math.max()
や Math.min()
に 配列そのまま 渡すとエラー!
OK例(正しいコード)
const rl = require('readline').createInterface({ input: process.stdin });
rl.on('line', (input) => {
const nums = input.split(' ').map(Number);
console.log(Math.max(...nums) - Math.min(...nums)); // スプレッド構文で展開
rl.close();
});
→ ...
(スプレッド構文)を使うことで、配列の要素を 個別の引数 として渡せる!
解説
-
Math.max()
やMath.min()
は 個別の引数 を受け取る関数 - 配列をそのまま渡すと 型が合わずエラー
- スプレッド構文 (
...
) を使うと、配列の中身が展開される!
まとめ
✅ Math.max()
や Math.min()
に 配列を直接渡さない
✅ スプレッド構文 (...
) で配列を展開 して渡す
✅ デバッグ時、「配列のまま渡してない?」をチェック!
おまけ: スプレッド構文 (...) ってなに?
### ❓ なぜ `Math.min()` や `Math.max()` に使うの?
Math.min()
や Math.max()
は 複数の数を引数として渡す関数。
でも 配列をそのまま渡してもダメ だから、スプレッド構文でバラしてあげる!
❌ うまくいかない例
const numbers = [3, 5, 1, 9, 2];
console.log(Math.min(numbers)); // NaN(計算できない)
console.log(Math.max(numbers)); // NaN
→ 配列のまま渡すと 1つの値(配列)と認識されてしまう からエラーになる💦
⭕ 正しいやり方(スプレッド構文を使う)
const numbers = [3, 5, 1, 9, 2];
console.log(Math.min(...numbers)); // 1
console.log(Math.max(...numbers)); // 9
→ ...numbers
で 配列の中身をバラして渡せる からOK!
実際には Math.min(3, 5, 1, 9, 2)
になってるよ✨
スプレッド構文ってどんなときに使うの?
① 配列をくっつけるとき
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
→ concat()
を使わずに簡単にくっつけられる!
② 配列をコピーするとき
const original = [10, 20, 30];
const copy = [...original];
console.log(copy); // [10, 20, 30]
→ copy = original
だと 同じデータを参照 しちゃうけど、
...
を使うと 新しい配列を作れる!
③ 関数の引数に配列を渡すとき
function sum(a, b, c) {
return a + b + c;
}
const values = [5, 10, 15];
console.log(sum(...values)); // 30
→ sum(5, 10, 15)
と同じになるよ!
まとめ
- スプレッド構文 (
...
) は配列やオブジェクトの中身をバラして使う方法 -
Math.min()
やMath.max()
に配列を渡すときに便利! - 配列の結合・コピー・関数の引数として使う ことができる
スプレッド構文を使うと、コードが スッキリ・簡単・ミスしにくい からどんどん使おう! 🎉
❓...numbers で 配列の中身をバラして渡せる からOK!とあるけど、③の例にあたる?
✅ そう! Math.min(...numbers)
は、スプレッド構文を使って「関数の引数として配列を展開する」例だから、③の例にあたる!
詳しく説明すると…
✅ Math.min(...numbers) の仕組み
const numbers = [3, 5, 1, 9, 2];
console.log(Math.min(...numbers));
// ↓ 展開されてこうなる
console.log(Math.min(3, 5, 1, 9, 2)); // 1
→ Math.min()
は 複数の数を引数として受け取る関数 だから、スプレッド構文を使って numbers
の 中身を展開 することで正しく動く!
✅ ③の sum(...values) の仕組み
function sum(a, b, c) {
return a + b + c;
}
const values = [5, 10, 15];
console.log(sum(...values));
// ↓ 展開されてこうなる
console.log(sum(5, 10, 15)); // 30
→ ここでも、スプレッド構文を使って 配列の要素をバラして関数に渡している から Math.min(...numbers)
と同じ考え方!
✅ Math.min(...numbers) と sum(...values)
どちらも「関数の引数として配列を展開する」用途だから、③の例にあたるよ!💡