Paizaの問題で、2次元配列のソートにハマった話。sort() は知ってたけど、配列の中に配列があると意外と難しい! 「りんごが多い方が偉く、同数ならバナナで勝負」 というルールを実装する方法を解説!
⭐問題概要
ペアとして与えられた「りんごの数」「バナナの数」をソートする。
📌 入力例
3 //ペアの数が与えられる
2 2
2 3
3 1
📌 出力例
3 1
2 3
2 2
⭐失敗例
❌ 文字列のままソート
const lines = ["2 2", "2 3", "3 1"];
lines.sort((a, b) => b - a);
console.log(lines);
→ 文字列なので数値比較ができず失敗!
❌ NaN になる
const numbers = lines.map(Number);
numbers.sort((a, b) => b - a);
console.log(numbers);
→ map(Number) では "2 2" のような複数の値を変換できず NaN!
⭐解決策(OKコード)
const rl = require('readline').createInterface({input: process.stdin});
const lines = [];
rl.on('line', (input) => lines.push(input));
rl.on('close', () => {
const pairs = lines.slice(1).map(pair => pair.split(" ").map(Number));
pairs.sort((a, b) => (b[0] - a[0]) || (b[1] - a[1]));
pairs.forEach(numbers => console.log(numbers.join(" ")));
});
✅ 修正ポイント
・.map(pair => pair.split(" ").map(Number)) で2次元配列を作成
・ソート時に b[0] - a[0] でりんご、b[1] - a[1] でバナナを比較
・forEach + join(" ") で出力!
⭐まとめ
sort() の比較関数をしっかり書けば、2次元配列も簡単にソートできる! NaN でハマった人は、数値変換と比較の順序を意識するとスムーズに解決!
↓ ⭐おまけ
||
を使った比較関数の仕組み
この書き方は 「短絡評価(ショートサーキット評価)」 を利用したテクニック。
||
は論理 OR ですが、JavaScript では 、
「左側が 0(または false 相当の値)なら右側を評価する」 という特性があります。
pairs.sort((a, b) => (b[0] - a[0]) || (b[1] - a[1]));
✅ 動作の流れ
📌まず b[0] - a[0]
を評価(りんごの数を降順ソート)
b[0] - a[0]
が 0
でなければ その値がそのまま返る(りんごの数が違う場合はここで決着)。
📌りんごの数が同じなら b[1] - a[1]
を評価(バナナの数を降順ソート)
b[0] - a[0] === 0
の場合、b[1] - a[1]
を返してバナナの数で並べ替える。
||
の評価ルール
console.log(10 || 5); // 10(最初の真の値を返す)
console.log(0 || 5); // 5(0は偽なので、次を評価)
console.log(0 || -1); // -1(0が偽なので、次を評価)
同様に、比較関数の ||
も 「左の比較が 0 なら右の比較をする」 という動作になる。
if
を使った普通の書き方
||
を使わずに書くと、こうなる!:
pairs.sort((a, b) => {
if (a[0] !== b[0]) {
return b[0] - a[0]; // りんごの数を比較
}
return b[1] - a[1]; // りんごが同じならバナナの数を比較
});
||
を使うとこれが1行で書ける ということ!
||
の注意点
このテクニックは 「値が 0(または false 相当の値)のときだけ次を評価する」 ので、
例えば null
や undefined
の比較では意図しない動作になる可能性がある。
シンプルな数値比較には便利だけど、何でもかんでも ||
でつなぐのは注意!
まとめ
・||
は OR だけど、 左が 0 なら右の値を返す 性質を利用している!
・b[0] - a[0]
が 0
(同じ値)なら b[1] - a[1]
で比較する。
・普通に if
で書くより短くてスッキリ!