どうも、Paizaで修行中の男子高校生です!
今回はPaizaの問題集から「文字列の出現回数を辞書順でカウントして出力する」という、データ構造(Map
)の理解を深めるにはもってこいの問題に挑戦したよ!
🧩 問題の内容
文字列がN個与えられます。
各文字列の出現回数を、文字列の辞書順に出力してください。
📥 入力例
5
bcd
abc
bcd
bcd
bcd
📤 出力例
abc 1
bcd 4
👊 最初に書いたバージョン
const rl = require('readline').createInterface({input:process.stdin});
const lines = [];
rl.on('line',(input)=>{
lines.push(input);
});
rl.on('close',()=>{
const N = Number(lines[0]);
const str = new Map();
for(let i = 1; i <= N; i++){
if(str.has(lines[i])){
str.set(lines[i], str.get(lines[i]) + 1)
}else{
str.set(lines[i], 1);
}
}
const keys = Array.from(str.keys()).sort();
keys.forEach(a=>{
console.log(a, str.get(a));
});
});
正直、これでも正解出せたけど、if
で分岐してset
するのがちょっと面倒…
✅ スマートなバージョンはこちら!
const rl = require('readline').createInterface({ input: process.stdin });
const lines = [];
rl.on('line', (input) => lines.push(input));
rl.on('close', () => {
const countMap = new Map();
lines.slice(1).forEach(word => {
countMap.set(word, (countMap.get(word) || 0) + 1);
});
[...countMap.entries()]
.sort((a, b) => a[0].localeCompare(b[0]))
.forEach(([word, count]) => {
console.log(word, count);
});
});
🔍 解説いっぱい!
🧠 countMap.set(word, (countMap.get(word) || 0) + 1)
countMap.get(word)
→ 今までにその単語が登録されてればカウント(例:3
)
→ 登録されてなければ undefined
countMap.get(word) || 0
→ 未登録なら undefined || 0 → 0
になる!
つまり… 「まだ出てきてなければ 0 からカウント開始」ってこと!
🔧 [...countMap.entries()]
entries()
は Map
の中身(key
, value
のペア)を取り出すメソッド。
MapIterator
っていう特殊な形式だから、[...
](スプレッド構文)で 普通の配列に変換!
const map = new Map();
map.set("apple", 3);
map.set("banana", 2);
const iterator = map.entries();
console.log(iterator);
// → MapIterator { ['apple', 3], ['banana', 2] }
// スプレッド構文を使って配列に変換
const array = [...iterator];
console.log(array);
// → [ ['apple', 3], ['banana', 2] ]
🔡 .sort((a, b) => a[0].localeCompare(b[0]))
a
と b
は [word, count]
の形の配列。
a[0]
が単語だから、それを localeCompare()
で比較!
console.log("apple".localeCompare("banana")); // -1(辞書順で前)
console.log("banana".localeCompare("apple")); // 1(後)
console.log("apple".localeCompare("apple")); // 0(同じ)
通常の .sort()
だけだと、日本語や他の言語でうまく並ばないこともある。
localeCompare()
を使えば、**人間が読む「自然な並び」**になる!
🔁 .forEach(([word, count]) => { ... })
分割代入で [word, count]
を取り出して、console.log
!
.forEach(([word, count]) => {
console.log(word, count);
});
🎯まとめ:この一連の流れ、1行ずつちゃんと意味ある!
[...countMap.entries()] // Map → 配列
.sort(...) // 辞書順ソート
.forEach(...) // 出力