2
1

More than 3 years have passed since last update.

javascriptでdeepcopyのようなことをやってみる

Last updated at Posted at 2019-12-25

この記事でやること

pythonを触っているときにcopyを使えば二次元配列も簡単にコピーできることに感動しました。

以前にjavascriptで同じことをやろうと思ったときに詰まった経験があるので、
javascriptの二次元配列やオブジェクトの配列をコピーする方法を残しておこうと思います。

はじめに

まず、javascriptである配列を別変数に代入した場合、その変数の値を変更すると元の配列にも影響します。

deepcopy.js
    const arr1 = [0, 1, 2];
    const arr2 = arr1;
    arr2[0] = 5;
    console.log(arr1); // [5, 1, 2]

このパターンでよく使われるのがこちらです。

deepcopy.js

    // パターン1
    const arr1 = [0, 1, 2];
    const arr2 = [].concat(arr1);
    arr2[0] = 5;
    console.log(arr1);  // [0, 1, 2]

    // パターン2
    const arr1 = [0, 1, 2];
    const arr2 = arr1.map( item => item);
    arr2[0] = 5;
    console.log(arr1); // [0, 1, 2]

    // パターン3
    const arr1 = [0, 1, 2];
    const arr2 = Array.from(arr1);
    arr2[0] = 5;
    console.log(arr1);  // [0, 1, 2]

    // パターン4
    const arr1 = [0, 1, 2];
    const arr2 = [...arr1];
    arr2[0] = 5;
    console.log(arr1);  // [0, 1, 2]

などです。
この他にもいくつか方法はあるかもしれません。

しかし、これらの方法でも二次元配列ではうまくいきません。

deepcopy.js

    const arr1 = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]
    ];
    const arr2 = [...arr1];
    arr2[0] = [1, 2, 3];
    console.log(arr1);
    // [[0, 1, 2],
    // [3, 4, 5],
    // [6, 7, 8]]

上記の例の場合では元の配列arr1には影響がありません。
しかし次の場合にうまく動作しません。

deepcopy.js
    const arr1 = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]
    ];
    const arr2 = [...arr1];
    arr2[0][0] = 5;
    console.log(arr1);
    // [[5, 1, 2],
    // [3, 4, 5],
    // [6, 7, 8]]

この場合は元の配列に影響を及ぼしてしまいます。

二次元配列の場合

そこで二次元配列の場合は次のようにします。

deepcopy.js

    // パターン1
    const arr1 = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]
    ];
    const arr2 = arr1.map( item => [].concat(item));
    arr2[0][0] = 5;
    console.log(arr1);
    // [[0, 1, 2],
    // [3, 4, 5],
    // [6, 7, 8]]

    // パターン2
    const arr1 = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]
    ];
    const arr2 = arr1.map( item => [...item]);
    arr2[0][0] = 5;
    console.log(arr1);
    // [[0, 1, 2],
    // [3, 4, 5],
    // [6, 7, 8]]

このようにするとうまくいきます。
オブジェクトの配列なども同様にすれば良いです。

deepcopy.js
    const arr1 = [
      { name: 'hoge', age: 19 },
      { name: 'fuga', age: 25 },
      { name: 'foo',  age: 22 }
    ];
    const arr2 = arr1.map( item => Object.assign({}, item));
    arr2[0].name = 'fuga';
    console.log(arr1);
    // {name: "hoge", age: 19}
    // {name: "fuga", age: 25}
    // {name: "foo", age: 22}

まとめ

これをdeepcopyと読んでも良いのでしょうか?

javascriptでそのような配列を取り扱い、またコピーする必要がある機会に出くわすかはわかりませんが、次元が大きくなるにつれコードがとんでもなくなりそうです。

2
1
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
2
1