0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

りんご vs バナナ!2次元配列ソート?(おまけ:|| 短絡評価(ショートサーキット評価))

Posted at

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 相当の値)のときだけ次を評価する」 ので、
例えば nullundefined の比較では意図しない動作になる可能性がある。
シンプルな数値比較には便利だけど、何でもかんでも || でつなぐのは注意!


まとめ
|| は OR だけど、 左が 0 なら右の値を返す 性質を利用している!
b[0] - a[0] 0(同じ値)なら b[1] - a[1] で比較する。
・普通に if で書くより短くてスッキリ!

🔗 僕の失敗談と解決話!

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?