56
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

2次元配列の初期化(ES2015)

Last updated at Posted at 2016-11-09

1次元配列の初期化

配列を new Array で生成すると、各要素が undefined の配列が得られます。
ES2015では fill メソッドを用いることで、引数の値で初期化してくれます。

var arr = (new Array(3)).fill(0);

2次元配列の初期化

それでは、3×3の2次元配列を0で初期化するコードを紹介します。

従来の方法

これまでのJavaScriptでは、配列を2重ループを用いて初期化するのが定番でしたね。

es5.js
var x, y;
var tbl = new Array(3);
for(y = 0; y < 3; y++) {
  tbl[y] = new Array(3);
  for(x = 0; x < 3; x++) {
    tbl[y][x] = 0;
  }
}

実際のところ、これで充分なのですが、ES2015の書式でもっとすっきりさせてみたいと思います。

失敗例

failed.js
var tbl = (new Array(3)).fill((new Array(3)).fill(0));

冒頭の1次元配列でのfillを使った書き方に倣って、fillを2重にしてみました。
最初書いてみて、これで万事OK、と思っていたのですが、実際このコードには欠陥があります。

var tbl = (new Array(3)).fill((new Array(3)).fill(0));
tbl[1][1] = 5;
console.log(tbl[1][1]); // => 5
console.log(tbl[2][1]); // => 5

このコードのように、2次元配列内の要素を1つ上書きしただけのはずなのに、
違う行の要素まで書き換わってしまっています。

それもそのはず、fillの中に入れた配列がプリミティブ値でないため、参照が各行とも同じになってしまっているのです。

以下のコードとやってることは同じです。

var row = (new Array(3)).fill(0);
var tbl = [row, row, row];
row[1] = 5;
console.log(tbl[1][1]); // => 5
console.log(tbl[2][1]); // => 5

正しい書き方

方法1

最初に試した方法を利用します。

method-1.js
var tbl = JSON.parse(JSON.stringify((new Array(3)).fill((new Array(3)).fill(0))));

配列をいったんJSON化して、それを再度オブジェクト化することによって、全ての配列が別オブジェクトになります。

方法2

いったん1×3の配列を作り、それぞれの行を forEach を使って配列にすげ替えます。

method-2.js
var tbl = (new Array(3)).fill(0);
tbl.forEach((_, i) => {
  tbl[i] = (new Array(3)).fill(0);
});

あまり効率的な感じはしませんね…。

方法3

これが一番素直でよいでしょう。

method-3.js
var tbl = new Array(3);
for(let y = 0; y < 3; y++) {
  tbl[y] = new Array(3).fill(0);
}

ES2015の記法で1重ループに抑えることができました。

他にもっとすっきりした初期化方法があればコメントください。

追記 すっきりした汎用コード

現時点でお二方からコメントくださって、両方ともES2015らしい書き方だと思ったので、行数列数を任意に変えられる汎用コードもご用意しました。

method-new-1.js
generate2DArray1 = (m, n, val = 0) => {
  return Array.from(new Array(m), _ => new Array(n).fill(val));
};
method-new-2.js
generate2DArray2 = (m, n, val = 0) => {
  return [...Array(m)].map(_ => Array(n).fill(val));
}
56
50
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?