Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

Array#fill中でArray#fillをやると特定セルだけ更新という事ができない

shuzo-kino.hateblo.jp
上記の記事で紹介したArray#fill中でArray#fillを呼び出す方式だと、特定セルだけ更新という事ができません。
……for文のネストは使ったら負けな気がするので、ここはmathjs使ったほうが良いように感じました。

実際のところ。

まず、単純な2x2の-1で満たされた多次元配列の要素一個を変えるケースを考えます。
何も考えずに力技。意図通りに動きます。

bar = [[-1,-1],[-1,-1]]
//[ [ -1, -1 ], [ -1, -1 ] ]
bar[0][0] = 8
//8
bar
//[ [ 8, -1 ], [ -1, -1 ] ]

個別にArrayから起こしても同じ。

bar = [Array(2).fill(-1),Array(2).fill(-1)]
//[ [ -1, -1 ], [ -1, -1 ] ]
//bar[0][1] = 8
8
> bar
[ [ -1, 8 ], [ -1, -1 ] ]

ところがギッチョン、これを前回の記事でやったようなArray#fill利用の多重挿入にすると……

> bar = Array(2).fill(Array(2).fill(-1))
[ [ -1, -1 ], [ -1, -1 ] ]
> bar[0][1] = 8
8
> bar
[ [ -1, 8 ], [ -1, 8 ] ]

これでは意図通りの挙動になりません。
ちなみにこれ、文字や数値では発生しないケースです。
C言語のポインタみたいに同一のオブジェクトを参照しに行ってるのが原因?

一方、mathjsのsubset関数ならそういった心配はありません。
今度は前回と同様9x16の規模に拡大し1,1の要素を3にしてみます。

math = require('mathjs')
a = math.matrix().resize([9,16],-1)
a.subset(math.index(1,1),3)
/*
Matrix {
  _data: 
   [ [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
     [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ] ],
  _size: [ 9, 16 ],
  _datatype: undefined }
*/

今度はうまくいきましたね。