Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
41
Help us understand the problem. What are the problem?
@butchi_y

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

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らしい書き方だと思ったので、行数列数を任意に変えられる汎用コードもご用意しました。

generate2DArray1 = (m, n) => {
  return Array.from(new Array(m), _ => new Array(n).fill(0));
};
generate2DArray2 = (m, n) => {
  return [...Array(m)].map(() => Array(n).fill(0));
}
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
41
Help us understand the problem. What are the problem?