はじめに
オンラインのコーディング問題を解く際に標準入力からカンマ区切りや改行区切りなどでパラメーターが与えられるケースがありますが、問題によって数値、文字列、配列など様々な受け取り方が必要となり、試行錯誤してしまうときがあります。
本質的でないところで手間取るのは思考も途切れてもったいないため、できるだけ簡潔に一発で所望の変数に格納できる方法を考えました。
コード全体
stdin.js
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", () => {
// Change left-hand side dependent on input
const [x, y] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
console.log(x, y);
});
ケース1: 文字列が改行区切りで与えられる
const [s, t] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
console.log(s, t);
実行例
$ node stdin.js
ABCDEF
GHIJKL
(press Ctrl+d)
ABCDEF GHIJKL
ケース2: 文字列がカンマ区切りや改行区切りで与えられる
const [x, y, z] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
console.log(x, y, z);
実行例
$ node stdin.js
ABC, DEF
GHI
(press Ctrl+d)
ABC DEF GHI
ケース3: 数値と複数の文字列が改行区切りで与えられる
const [n, ...pets] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
console.log(n, pets);
実行例
$ node stdin.js
3
dog
cat
hamster
(press Ctrl+d)
3 [ 'dog', 'cat', 'hamster' ]
ケース4: 小数や負の数が与えられる
const [...nums] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
実行例
$ node stdin.js
0.2
-9
-4.5
(press Ctrl+d)
[ 0.2, -9, -1.2 ]
ケース5: 解説用
console.log(lines.map(e => e.split(/[,\s]/).filter(e => e != "")));
console.log(lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat());
console.log(lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e));
実行例
$ node stdin.js
3.5
flower, -9, coffee
book, 2.5
(press Ctrl+d)
[ [ '3.5' ], [ 'flower', ' -9', 'coffee' ], [ 'book', ' 2.5' ] ]
[ '3.5', 'flower', ' -9', 'coffee', 'book', '2.5' ]
[ 3.5, 'flower', -9, 'coffee', 'book', 2.5 ]
解説
- オンラインの問題では入出力がインタラクティブに行われるようなケースはあまりないので、入力終了となるまで一発で受け取り、後続で処理するための変数や配列に一発で格納することを目的としています。
-
lines.map()
で各要素に対しカンマ&空白文字区切りでさらに要素を展開したのち、空白文字区切りにより展開されてしまう空文字要素をfilter()
で削除します。 - 次に、
flat()
で2次元配列を1次元配列に変換します。 - 最後に、
isFinite()
で有限数かどうか判断して真なら単項演算子+
をつけることで数値に変換します。isFinite()
による判定を挟まないと数値でない場合に"NaN"に変換されてしまうので注意が必要です。 - よくある「Nという数値が入力されたのち、続けてN個の文字列が入力されます」というパターンでは
[n, ...params]
のように残りの文字列を残余引数を使用して配列で受けてください。
参考にした記事