Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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重ループに抑えることができました。

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

butchi_y
博士(工学)のフロントエンドエンジニアです。 ローレベルな言語仕様から、アニメーション演出まで幅広く興味を持ってます。 得意な言語はMathematica、JavaScript、ActionScriptです。 CGや音楽にもそれなりに詳しいです。
http://butchi.jp
kayac
古都鎌倉から新しい技術と面白いサービスを、次々にリリースする面白法人カヤックのフロントエンジニアチーム
http://www.kayac.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした