本記事は、paizaラーニング「レベルアップ問題集」の学習記録です。
同コーナーでは、解答やコードの公開が認められています。
問題
10個の文字列 S_1, S_2, S_3, ..., S_10 が、改行区切りで入力されます。
入力されたすべての文字列を、半角スペース区切りで1行にして出力します。
入力例
q
bpdi
u
ky
meqt
rrnc
co
jjw
e
fwio
出力例
q bpdi u ky meqt rrnc co jjw e fwio
最初に考えたコード
process.stdin.resume();
process.stdin.setEncoding("utf8");
var lines = [];
var reader = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
reader.on("line", (line) => {
lines.push(line);
});
reader.on("close", () => {
const input = lines[0].split(" ");
i = 0;
for (let = i; i => 10; i++) {
console.log(lines[i]);
}
});
10個の文字列を順番に出力しようとして、for 文を使おうとしました。
しかし、この書き方では正しく出力できませんでした。
正解コード
process.stdin.resume();
process.stdin.setEncoding("utf8");
const lines = [];
const reader = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
reader.on("line", (line) => {
lines.push(line);
});
reader.on("close", () => {
console.log(lines.join(" "));
});
解説
入力された文字列は lines に入っている
次の部分で、入力を1行ずつ受け取っています。
reader.on("line", (line) => {
lines.push(line);
});
入力例の場合、lines の中身は次のようになります。
[
"q",
"bpdi",
"u",
"ky",
"meqt",
"rrnc",
"co",
"jjw",
"e",
"fwio"
]
lines は、10個の文字列が入った配列です。
join(" ") とは
今回のポイントは、次のコードです。
console.log(lines.join(" "));
join() は、配列の要素をつなげて、1つの文字列にするメソッドです。
今回は、丸括弧の中に半角スペースを指定しています。
join(" ")
そのため、配列の要素が半角スペース区切りでつながります。
["q", "bpdi", "u"]
この配列に対して、
lines.join(" ")
を実行すると、次の文字列になります。
q bpdi u
なぜ split(" ") は必要ないのか
最初は、次のように書いていました。
const input = lines[0].split(" ");
split() は、1つの文字列を分割して、配列にするメソッドです。
しかし、今回の入力は最初から改行区切りです。
readline を使った時点で、それぞれの文字列はすでに lines の中へ別々に入っています。
そのため、改めて split() を使う必要はありません。
また、lines[0] は最初の文字列である "q" だけです。
lines[0]
q
この "q" を半角スペースで分割しても、結果は変わりません。
["q"]
今回使いたいのは、最初の要素だけではなく、配列全体の lines です。
console.log() を10回使うと改行されてしまう
次のように書くと、
console.log(lines[0]);
console.log(lines[1]);
console.log(lines[2]);
出力は改行区切りになります。
q
bpdi
u
しかし、今回求められているのは半角スペース区切りです。
q bpdi u
そのため、すべての文字列を join(" ") でつなげてから、最後に1回だけ console.log() で出力します。
for 文で書く場合
join() を使わずに、for 文で書くこともできます。
reader.on("close", () => {
let result = "";
for (let i = 0; i < 10; i++) {
if (i > 0) {
result += " ";
}
result += lines[i];
}
console.log(result);
});
処理の流れ
最初に、出力する文字列を入れる変数を用意します。
let result = "";
for 文で、lines の中身を順番に取り出します。
for (let i = 0; i < 10; i++) {
2個目以降の文字列の前には、半角スペースを追加します。
if (i > 0) {
result += " ";
}
その後、文字列を追加します。
result += lines[i];
最後に、完成した文字列を出力します。
console.log(result);
ただし、今回のように配列の中身を同じ区切り文字でつなげる場合は、join() を使うほうが簡単です。
for 文の間違い
最初に書いた for 文には、いくつか修正点があります。
間違ったコード
i = 0;
for (let = i; i => 10; i++) {
console.log(lines[i]);
}
正しい書き方
for (let i = 0; i < 10; i++) {
console.log(lines[i]);
}
for 文の基本形は次のとおりです。
for (初期化; 条件; 増減) {
処理
}
今回の場合は次のようになります。
for (let i = 0; i < 10; i++) {
-
let i = 0
0番目から開始する -
i < 10
iが10未満の間、繰り返す -
i++
1回処理するごとに、iを1増やす
また、
i => 10
の => は、大小を比較する記号ではありません。
「10以上」を表す場合は、次のように書きます。
i >= 10
今回必要なのは、0から9まで繰り返す条件なので、
i < 10
となります。
ただし、この問題で console.log(lines[i]) を繰り返すと、文字列が改行区切りで出力されます。
そのため、問題の条件に合わせるには、join(" ") を使うのが分かりやすいです。
まとめ
今回のポイントは、次の3つです。
-
readlineで受け取った各行は、lines配列に入る - 配列の要素をつなげるときは
join()を使える - 半角スペース区切りにしたい場合は
join(" ")と書く
今回の答えは、次の1行です。
console.log(lines.join(" "));
配列の中身をカンマ、半角スペース、改行などでつなげたい場合に、join() はよく使うため覚えておきたいです。