【问题标题】:How can I clone a tree structure of an array of objects to another one, changing attributes to the cloned?如何将对象数组的树结构克隆到另一个对象,将属性更改为克隆对象?
【发布时间】:2020-10-14 15:53:56
【问题描述】:

如何将一组对象的树结构克隆到另一个对象,在 TypeScript 中对克隆的对象具有不同或更少的属性? 例如关于这个:

[
   {
      "name":"root_1",
      "extradata":"whatever",
      "anArray":[
         { "id":1, "value":"test" },
         { "id":1, "value":"test" }
      ],
      "anObject":{ "id":1, "value":"test" },
      "children":[
         {
            "name":"child_1",
            "extradata":"whatever",
            "anArray":[],
            "anObject":{},
            "children":[
               {
                  "name":"root_1",
                  "extradata":"whatever",
                  "anArray":[],
                  "anObject":{},
                  "children":[]
               },
               {
                  "name":"root_1",
                  "extradata":"whatever",
                  "anArray":[],
                  "anObject":{},
                  "children":[]
               }
            ]
         }
      ]
   },
   {
      "name":"root_2",
      "extradata":"whatever",
      "anArray":[],
      "anObject":{},
      "children":[]
   }
]

我需要它的克隆,但不是“命名”属性“标签”,而是“extradata”=“key”并且没有“anArray”和“anObject”。像这样:

[
   {
      "label":"root_1",
      "key":"whatever",
      "children":[
         {
            "label":"child_1",
            "key":"whatever",
            "children":[
               {
                  "label":"root_1",
                  "key":"whatever",
                  "children":[]
               },
               {
                  "label":"root_1",
                  "key":"whatever",
                  "children":[]
               }
            ]
         }
      ]
   },
   {
      "label":"root_2",
      "key":"whatever",
      "children":[]
   }
]

我需要克隆它,使用它作为primeng树组件的数据格式。

我正在尝试类似的东西

this.myTree = tree.map((m, index) => Object.assign({}, {
                                label: m.name,
                                key: m.extradata,
                                children: m.children
                            }));

但是孩子们没有遵循相同的形状。

【问题讨论】:

    标签: angular typescript primeng-tree


    【解决方案1】:

    我会首先为有问题的输入和输出类型定义接口:

    interface InputTree {
      name: string,
      extradata: string,
      anArray: any[],
      anObject: object,
      children: InputTree[]
    }
    
    interface OutputTree {
      label: string,
      key: string,
      children: OutputTree[];
    }
    

    根据该定义,您的输入看起来像是 InputTree[],而您想要生成 OutputTree[]。树是递归的,因此您应该编写一个treeMap() 函数,该函数对InputTree[] 进行操作,然后在数组中每个InputTree 的children 上递归调用自身。像这样:

    const treeMap = (inputTree: InputTree[]): OutputTree[] => inputTree.map(t => ({
      label: t.name,
      key: t.extradata,
      children: treeMap(t.children)
    }));
    
    const actual = treeMap(tree);
    

    您可以验证这是否产生了您期望的输出:

    console.log(JSON.stringify(expected)===JSON.stringify(actual)); // true
    

    Playground link to code

    【讨论】:

    • 我喜欢你在界面方面的想法,感谢你在 typescriptlang 中进行测试。事实上,响应来自ngrx/store,并且已经映射到模型中。我没有得到如何使用递归调用来获得我需要的结果。你能把它添加到示例中吗?
    • 怎么添加?可以看到treeMap()的实现调用了treeMap(),对吧?在inputTree.map(t => ({...}) 中,需要在... 中设置属性。 label 和key 属性只能从t 复制,但children 属性是InputTree[],您需要它是OutputTree[]。幸运的是,我们正在编写一个将前者转换为后者的函数,因此children 属性变为treeMap(t.children)。
    • 我现在必须尝试使用​​商店数据,它工作正常。非常感谢大佬,非常感谢。我想不出这样的用法,我在 tree.map((m, index) => Object.assign({},.
    • 你知道我该如何包装 OutputTree:{ "data": [ ] } 最后它应该是这样的:github.com/primefaces/primeng/blob/master/src/assets/showcase/…
    • 喜欢this?它不会取代treeMap;它正在使用它。 cmets中的这些后续问题似乎超出了原问题的范围,所以我不确定我可以在这里互动多久。如果您有一个新问题,您可能想开始一个新问题以引起更多关注。祝你好运!
    【解决方案2】:

    我不确定您是否可以使用 3rd 方库 - 但您听说过 loadsh 吗? 有很多关于如何实现这一点的例子(:

    first example

    second example

    如果你不能使用它,我会在代码中 dive 看看他们是如何实现它的(:

    【讨论】:

    • 感谢您的回答。我在类似问题中将其视为参考,但不,我不能使用它,从示例中我什至不确定它是否可以在这样的树结构中工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 2015-02-08
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多