はじめに
Javascriptで数値の入った配列に対して何らかの操作をしようとしたとき、簡単な処理でも適当なapiがないために自分で実装しなくてはならないことが多い。またモダンな記法を知らないがために、愚直に実装しコードが冗長になってしまうこともある。そこでここでは数値配列を扱うときによく出てくる操作を効率的に実装するためのtipsをまとめる。
*順次更新していきます。
1次元配列
配列[0,1,2,...,n]の生成
[...Array(5).keys()]; // => [0,1,2,3,4]
Array.from(Array(5).keys()); // => [0,1,2,3,4]
どちらも同様な結果を与える。短いので以下では上の記法を用いる。
配列[0,0,...,0](要素が全て0の配列)の生成
[...Array(5)].map( e => 0 ); // => [0,0,0,0,0]
配列のクローン
単に
let x = [1,3,5,-2,4];
let y = x;
とすると、y
の要素を変えると、x
の要素も変わってしまう。
let y = x.slice();
y; // => [1,3,5,-2,4]
とすればx
の要素がy
にクローンされ、y
の要素を変えても、x
の要素は変わらない。
他にも
let y = [].concat(x);
let y = [...x];
let y = Array.from(x);
と言う方法もあるようです。調べてみると[...x]
とArray.from(x)
を使う方法はスピードが遅いようです。要素数が100000の配列に対するクローンの時間を計測してみると(1000回平均)、以下のようになりました。
x.slice() | [].concat(x) | [...x] | Array.from(x) |
---|---|---|---|
0.48ms | 0.50ms | 3.9ms | 7.7ms |
*@felisさんにslice()
に関するコメントをいただきました。ありがとうございました。
配列のソート
in-placeにソートしたいときには、
let x = [1,3,5,-2,4];
x.sort();
x; // => [-2,1,3,4,5];
とすれば良い。
ソートした値を他の変数にコピーしたいのならば、一旦コピーを作ってからソートすれば良い。
let x = [1,3,5,-2,4];
let y = x.slice().sort();
y; // => [-2,1,3,4,5]
配列をソートしたときのインデックスの配列
配列のインデックス[...x.keys()]
を要素の大小関係に従ってソートすれば良い。
let x = [1,3,5,-2,4];
[...x.keys()].sort( (i,j) => x[i]-x[j] ) // => [3,0,1,4,2] 昇順
[...x.keys()].sort( (i,j) => x[j]-x[i] ) // => [2,4,1,0,3] 降順
Javascriptのsort
関数は大小関係を定義するコールバック関数を渡すことができるので、インデックスを要素の値に従って並べ替えれば良い。
最大値・最小値を求める。
let x = [1,3,5,-2,4];
Math.max(...x); // => 5
Math.min(...x); // => -2
スプレッド演算子(...)で配列を展開してからMath.max() or Math.min()に渡すのがポイント。
最大値・最小値のインデックスを求める。
let x = [1,3,5,-2,4];
x.indexOf( Math.max(...x) ); // => 2
x.indexOf( Math.min(...x) ); // => 3
平均値を求める。
x.reduce( (a,c) => a+c )/x.length; // => 2.2
reduce()を用いて配列の要素をひとつづつ足していく。