47505
この質問はほぼマルチポストです。元の質問はこちらです。<https://teratail.com/questions/140995>  
teratailの方での質問の仕方に問題を感じたのもあり、より簡略化した質問をこちらにさせて頂きました。  
ご指摘頂いたので上記追記致します。

```

    let objectList = [
    
      {
        objectId : 1,
        objectName : "オブジェクト1",
        isLeaf : false,
        children : []
      },
      {
        objectId : 2,
        objectName : "オブジェクト2",
        isLeaf : true
      },
      {
        objectId : 3,
        objectName : "オブジェクト3",
        isLeaf : false, 
        children : []
      },
      {
        objectId : 4,
        objectName : "オブジェクト4",
        isLeaf : true
      },
      {
        objectId : 5,
        objectName : "オブジェクト5",
        isLeaf : false,
        children : []
      },
    
    ]
    
```

このような配列があった場合に

```

    let updatedObjectList = [
      {
        objectId : 5,
        objectName : "オブジェクト5",
        isLeaf : false,
        children : []
      },
      {
        objectId : 3,
        objectName : "オブジェクト3",
        isLeaf : false,
        children : [
          {
            objectId : 2,
            objectName : "オブジェクト2",
            isLeaf : true
          },
          {
            objectId : 1,
            objectName : "オブジェクト1",
            isLeaf : false,
            children : [
              {
                objectId : 4,
                objectName : "オブジェクト4",
                objectList : [],
                isLeaf : true
              },
            ]
          },
        ]
      }
    ]
    
```

こちらのupdatedObjectListと同じ構造に、objectListをしたいです...。  
ただし、objectList = updatedObjectList とするのではなく、  
**objectListをソートすることで、updatedObjectListと同じ構造にしたいです。**

```

    //linq-es2015使用しております
    let objectList = this.objectList
    
    this.objectList = []
    
    for(var i = 0; i < updatedObjectList.length; i++){
                this.objectList.unshift(Enumerable.asEnumerable(objectList).Where(x=>x.objectId==updatedObjectList[i].objectId).ToArray()[0])
    }
    
```

もし、childrenという概念がなく、ただ順番を入れ替えるだけなら上のような形でできるのですが、コードがスマートじゃないし、階層構造をどう表現するのか分からなく、困っております...。  
また逆に、階層構造を解除する(childrenに含めれたオブジェクトを外に出す)こともあります。  
どのような関数を作ればいいのか...。  
教えてくだされば幸いです(>_<)
CC BY-SA 4.0
2018-08-14T02:51:50.160
47499
2018-08-14T15:33:18.837
2018-08-14T15:33:18.837
3054
29725
question
javascript typescript
配列内のツリー構造を別の配列と合わせたい
性能上の問題が出ていないならば、入れ替えのような難しいことは考えずに、一から順に作り直すのが楽だと思います。

とりあえず、ごく素直に考えると以下のようになりました。  
作り直す前に元のオブジェクト達をどこかに保存しておかなければならないので、以下ではそれを `mkObjectTable`
にやらせていますが、質問の例のように元のリストが単純な一次元配列なら、そのままコピーしておけばいいですね。

```

    type MyObj = {
        objectId: number,
        children?: MyObj[],
    }
    
    function mkObjectTable(list: MyObj[], table: MyObj[] = []): MyObj[] {
        for (const o of list) {
            table[o.objectId] = o
            if (o.children != null) {
                mkObjectTable(o.children, table)
            }
        }
        return table
    }
    
    function copyStructure(src: MyObj[], dest: MyObj[], table: MyObj[] = mkObjectTable(dest)) {
        dest.length = 0
        for (const srcObj of src) {
            const destObj = table[srcObj.objectId]
            dest.push(destObj)
            if (srcObj.children != null && srcObj.children.length != 0) {
                if (destObj.children == null) {
                    destObj.children = []
                }
                copyStructure(srcObj.children, destObj.children, table)
            } else if (destObj.children != null) {
                destObj.children.length = 0
            }
        }
    }
    
    copyStructure(updatedObjectList, objectList)
    
```

* * *

> これって参照渡しみたいになってるのでしょうか

JavaScriptのオブジェクトは配列を含め、参照型です。  
ですから、関数に配列を渡すと関数内で書き変えられるという意味で「参照渡しみたい」と言ってよいと思います。  
（正確には「参照の値渡し」かも知れません。私はこのへんの用語はよく解りません）
CC BY-SA 4.0
2018-08-14T09:37:42.280
47505
2018-08-14T11:13:17.717
2018-08-14T11:13:17.717
3054
3054
47499
answer