やりたいこと
例えば長さ12の配列を、
変換前
const src = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
このように、
変換前
[
['Jan', 'Feb', 'Mar'],
['Apr', 'May', 'Jun'],
['Jul', 'Aug', 'Sep'],
['Oct', 'Nov', 'Dec']
]
長さ3など短い複数の配列に分割したいとします。これを実現するワンライナーを紹介します。
答え(ワンライナー)
答え
const dst = Array(Math.ceil(src.length/n)).fill().map((_, i) => src.slice(n*i, n*(i+1)));
- まず、
Math.ceil(src.length/n)
で分割数を求めます。例えば、長さ12を長さ3で分けるならちょうど4ですが、繰り上げが入るので長さ12を長さで5で分けた場合は2でなく3が導かれます。 -
Array(分割数).fill()
でfill()
を呼んでいるのは、単に配列を初期化しただけだとインデックス(オブジェクトのキー)がなく次に説明するmap()
が無効となってしまうためです。 -
map()
でループします。インデックスi
が取る値は0から分割数-1までとなります。 -
slice()
で元の配列から部分配列を切り取ります。slice(start, end)
のend
はend >= src.length
の場合でもsrc.length
が使用され、n
で割り切れないケースでも安全です。
実行例
サンプルコード
arrsplit.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 [n, ...src] = lines.map(e => e.split(/[,\s]/).filter(e => e != "")).flat().map(e => isFinite(e) ? +e : e);
const dst = Array(Math.ceil(src.length/n)).fill().map((_, i) => src.slice(n*i, n*(i+1)));
console.log(dst);
});
実行例1 (nで割り切れるとき)
$ node arrsplit.js
3
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
(press Ctrl+d)
[
[ 'Jan', 'Feb', 'Mar' ],
[ 'Apr', 'May', 'Jun' ],
[ 'Jul', 'Aug', 'Sep' ],
[ 'Oct', 'Nov', 'Dec' ]
]
実行例2 (nで割り切れないとき)
$ node arrsplit.js
5
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
(press Ctrl+d)
[
[ 'Jan', 'Feb', 'Mar', 'Apr', 'May' ],
[ 'Jun', 'Jul', 'Aug', 'Sep', 'Oct' ],
[ 'Nov', 'Dec' ]
]
所感
他にも余りがあるか判定を挟む方法や、reduce()
を使った方法など様々ありますが、上記が個人的には直感的で覚えやすく、かつ簡潔なのでバランスが良いと思っております。
オンラインのコーディング問題を解くときなどに、JavaScriptで標準入力から数値や文字列を一発で受け取る #JavaScript - Qiita と組み合わせて使っていただくと便利ではないかと思います。
参考
- JavaScriptで標準入力から数値や文字列を一発で受け取る
https://qiita.com/nakatahr/items/138b5cfe1c451c84b68d - JavaScriptでn個ずつ配列を分割する
https://yucatio.hatenablog.com/entry/2019/12/10/222311 - JavaScriptのnew Array(n)をmapしたいとき fillをはさむ理由
https://yucatio.hatenablog.com/entry/2019/04/07/110721 - JSで配列をn個ずつに分割
https://qiita.com/guttyar2213/items/46230300c5100a06198c - Array.prototype.slice()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice