【JS】２次元のオブジェクトの要素を変更・追加する方法

2次元のオブジェクトの要素を変更・追加するには、**mapを２回使う**必要がある。

2次元の要素の変換をした後、1次元の要素を変換する処理となる。


##目次

1. [要素の追加](#要素の追加)
2. [要素の変換](#要素の変換)
3. [要素の追加と変換](#要素の追加と変換)
4. [指定した要素のみ値を変更/追加](#指定した要素のみ値を変更追加)
5. [要素を変更/追加してから特定の要素を排除](#要素を変更追加してから特定の要素を排除)


##２次元のオブジェクトの要素を変更する実例

###要素の追加

`[{a:1, b:2, c:[{d:1, e:2}]}`のようなオブジェクトのプロパティcの値に`f:9`を新たに追加する場合は以下のようになる。

```js:
obj = [{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}

obj = obj.map( elem => {
      newC = elem.c.map( x => {
       return {...x, f: 9}
      })

      return {...elem, c: newC}
})

console.log(obj)
//[{a:1, b:2, c:[{d:1, e:2, f:9}]}, {a:3, b:4, c:[{d:3, e:4, f:9}]
```

・`obj.map( elem => {処理}`
まずは、元のオブジェクトにmapを使って、要素をひつづつ取り出す。

・`newC`
プロパティcに`f:9`を追加した要素を代入する変数を準備。

・`elem.c.map( x => {処理})`
元のオブジェクトの要素のプロパティcの要素を一つずつ取り出す。

ここでは　x = {d:1, e:2}　。
プロパティcの中に複数のオブジェクトがある場合は、一つづつ取り出す処理となる。

・`return {...x, f: 9}`
スプレッド構文でプロパティcを展開して、f:9 を追加した後、再度{ }で閉じる。これを戻り値とする。

この処理で、 newC = [{d:1, e:2, f:9}]　となる。

・`return {...elem, c: newC}`
１次元目のオブジェクトをスプレッド構文で展開し、作成したnewCをプロパティCの値に置き換える。

この処理で、　{a:1, b:2, c:[{d:1, e:2, f:9}]} となる。

これを要素の数だけ繰り返し完了となる。



<br>
##要素の変換
要素を変換する場合は、上記の処理で、プロパティcを展開した時に、変換したいプロパティを指定して値を代入すればOK。

```js:
obj = [{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}

obj = obj.map( elem => {
      newC = elem.c.map( x => {
       return {...x, d: 100}
      })

      return {...elem, c: newC}
})

console.log(obj)
//[{a:1, b:2, c:[{d:100, e:2}]}, {a:3, b:4, c:[{d:100, e:2}]
```

・`{...x, d: 100}`
この処理で、プロパティcの要素(x)を展開し、その中のプロパティdの値を100に変換している。



<br>
##要素の追加と変換
追加と変換を行う場合は、上記の処理を組み合わせる。

```js:
obj = [{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}

obj = obj.map( elem => {
      newC = elem.c.map( x => {
       return {...x, d: 100, f: 9}
      })

      return {...elem, c: newC}
})

console.log(obj)
//[{a:1, b:2, c:[{d: 100, e: 4, f: 9}]}, {a:3, b:4, c:[{d: 100, e: 4, f: 9}]
```

・`{...x, d: 100, f: 9}`
dを100に変更し、f: 9を新たに追加している。



<br>
##指定した要素のみ値を変更/追加
上記の例だと該当するプロパティを持つ要素が一括変換となる。

**ifで条件分岐を設ける**ことで、指定した要素のみ変換することができる。

<br>
**▼２番目の要素のみ変更・追加**

```js:
obj = [{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}

obj = obj.map( (elem, index) => {
    if(index==1){
            newC = elem.c.map( x => {
                 return {...x, d: 100, f: 9}
            })
            return {...elem, c: newC}

    } else {return elem}
})

console.log(obj)
//[{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d: 100, e: 4, f: 9}]
```

・`obj.map( (elem, index) => {  }`
mapの第２引数はインデックス番号を格納する変数となる。今回は、if文の条件としてこれを利用。

・`if( index == 1 ){ 処理 }`
インデックス番号が１の時のみ、newCを作成する処理を実行する。

・`else { return elem }`
ifの条件がtrue以外の時は、元の要素をそのまま返す。



<br>
##要素を変更/追加してから特定の要素を排除

オブジェクトに変更を加え、更に不要な要素を削除する場合は、**filterで指定条件に該当する要素を除外**すればOK。

例えば、以下のような３つの要素が入った２次元のオブジェクトで、2番目の要素のみプロパティを変更・追加し、１番目の要素を削除する場合を考える。

```:元のオブジェクト
[{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}, {a:5, b:6, c:[{d:5, e:6}]}]`
```
　　↓

```:処理後
[{a:3, b:4, c:[{d: 100, e: 4, f: 9}]}, {a:5, b:6, c:[{d:5, e:6}]}]
```


###▼コード実例

```js:
obj = [{a:1, b:2, c:[{d:1, e:2}]}, {a:3, b:4, c:[{d:3, e:4}]}, {a:5, b:6, c:[{d:5, e:6}]}]

obj = obj.map( (elem, index) => {
    if(index==1){
            newC = elem.c.map( x => {
                 return {...x, d: 100, f: 9}
            })

            return {...elem, c: newC}

    } else {return elem}
})
.filter( (_elem, _index) => {
        return !(_index == 0)
} )

console.log(obj)
//[{a:3, b:4, c:[{d: 100, e: 4, f: 9}]}, {a:5, b:6, c:[{d:5, e:6}]}]
```

オブジェクトの追加・変更処理はこれまでと同様。
最後に `filter`で、index番号が０となる要素を除外している。


<br>
２次元のオブジェクトを変更する場合は、mapを２つ使う。変換したい次元の数だけmapが入れ子になる。