Paizaの問題で、半角スペース区切りの文字列を出現順に出力した後、それぞれの出現回数を出力するというタスクに挑戦した。とりあえず Map
と forEach
を駆使したのだけれど、これはどうも無駄が多い…。調べたら配列を使うと最適化できることがわかった。その実装を共有しよう!
問題概要
👉 要求
- 半角スペース区切りの文字列を受け取る
- その中のユニークな単語を、登場順に出力
- その後、個々の単語の出現回数を出力
入力例:
red green blue blue green blue
出力例:
red
green
blue
1
2
3
🚨 シンプルながら無駄が多いコード
const rl = require('readline').createInterface({input: process.stdin});
rl.on('line', (input) => {
const words = input.split(" ");
const dict = new Map();
words.forEach(a => {
dict.set(a, 0); // まず0で初期化
});
words.forEach(a => {
dict.set(a, dict.get(a) + 1); // カウントアップ
});
dict.forEach((value, key) => {
console.log(key); // 単語を出力
});
dict.forEach(value => {
console.log(value); // 出現回数を出力
});
rl.close();
});
🛠️ order 配列を利用
const rl = require('readline').createInterface({ input: process.stdin });
rl.on('line', (input) => {
const words = input.split(" ");
const dict = new Map();
const order = []; // 単語の出現順を記録
words.forEach(word => {
if (!dict.has(word)) {
dict.set(word, 0);
order.push(word); // 初出の単語を記録
}
dict.set(word, dict.get(word) + 1); // カウント更新
});
// 出現順に単語を出力
order.forEach(word => console.log(word));
// 出現順にカウントを出力
order.forEach(word => console.log(dict.get(word)));
rl.close();
});
🤔 なぜ order 配列が必要なの?
-
order
に初出の単語を記録すれば、出力順を保証できる - ループを1回にまとめて、計算量を削減
📅 まとめ
-
Map
で単語の出現回数を管理 -
order
を利用して出現順を保証 -
forEach
を減らすだけで、キレイなコードに修正できる
🎧 この解決法で、パフォーマンスが向上した気がする!