Paizaの問題を解いていたら、「攻撃された人のダメージを記録し、名前の辞書順で出力せよ!」という指示に見事にハマった。Map
は順番を保持しないので、そのまま forEach()
すると順番が崩壊する!辞書順って何!? Map
にソート機能がない!?試行錯誤の末、「キーを配列化してソートすればいい」 という学びを得たので、その知見をシェアする!
問題概要
攻撃された人のダメージを記録し、名前の辞書順で出力。
入力例:
3 //n
PAIIZA
PAIZA
PAIIIZA
2 //m
PAIIZA 2
PAIIIZA 3
出力例:
3
2
0
NG例: Map に頼りすぎたコード
const damageMap = new Map();
for (let i = 1; i <= n; i++) {
damageMap.set(lines[i], 0);
}
for (let i = n + 2; i < n + 2 + m; i++) {
let [person, damage] = lines[i].split(" ");
damageMap.set(person, damageMap.get(person) + Number(damage));
}
damageMap.forEach((value, key) => console.log(value)); // 辞書順にならない!
ミスのポイント
✅ Map の挿入順に保証されている(辞書順にならない)
OK例1: Array.from()
でソート
const sortedNames = Array.from(damageMap.keys()).sort();
sortedNames.forEach(name => console.log(damageMap.get(name)));
✅ Array.from() でキーを取り出し、sort() で辞書順ソート
✅ get() を使い、順番に出力
OK例2: slice()
で無駄を省く
const sortedNames = lines.slice(1, n + 1).sort();
sortedNames.forEach(name => console.log(damageMap.get(name)));
✅ すでに lines に名前があるので Map.keys() 取得不要
✅ キーアクセス回数が減り、わずかにパフォーマンス向上
まとめ
Map は順序を保証しない!辞書順ソートが必要なら、
・Array.from(damageMap.keys()).sort()
・もともとのリストを slice().sort() で利用
これで Map の罠にはまらない!