创建与另一个具有相同形状的树数据结构

时间:2018-06-16 21:36:11

标签: javascript typescript recursion tree

假设我有一个典型的树数据结构,如下所示:

[
  {
    att1: 'asdasd',
    att2: 42,
    att3: true,
    subs: [ ...other objects... ]
  },
  ...other objects...
]

它可以有任何形状和数量的节点,但每个节点都有这三个属性(当然每个节点都有不同的值)。

现在,我想创建一个具有完全相同层次结构的新树,但它应该保存数据,让我们以这样的格式说:

[
  {
    data: { att1: 'asdasd', att2: 42, att3: true },
    subs: [ ...other objects... ]
  },
  ...other objects...
]

(实现这一目的的一种方法是编写一个访问原始树的每个节点的递归函数,为每个节点创建data属性,用三个属性填充其内容{{ 1}},att1att2,然后删除节点的这些属性。这样我就会拥有这个新树。但我不想改变原始树,所以这是对我来说不是一个选项。我也不想使用att3或以其他方式克隆树,然后对这个新树执行上述相同的过程。)

相反,我正在寻找一种方法来按节点生成这个新的树节点,因为我正在按节点读取原始树节点。

我已经可以编写的方法访问原始树的每个节点:

JSON.parse(JSON.stringify())

我怎样才能完成这个方法(或者你也可以给我看一个不同的实现)来生成新的树?

3 个答案:

答案 0 :(得分:2)

如果您首先为输入和输出形状定义接口,可以使用它们以及任何产生的TypeScript错误来帮助指导您:

interface Attributes {
    att1: string;
    att2: number;
    att3: boolean;
}

type InputNode = Attributes & {
    subs: InputNode[];
}

interface OutputNode {
    data: Attributes;
    subs: OutputNode[];
}

有了这些,我们可以将函数定义设置为

function copyTree(originalTree: InputNode[]): OutputNode[] {

然后你可以使用rest / spread来帮助转移所有内容:

function copyTree(originalTree: InputNode[]): OutputNode[] {
    return originalTree.map(input => {
        const {
            subs,
            ...data
        } = input;

        return {
            subs: copyTree(subs),
            data,
        };
    });
}

答案 1 :(得分:1)

好吧,我会使用map和传播/休息运算符来执行此操作:

const array = [...];

const copy = array.map(item => {
    const {att1, att2, att3, ...rest} = item;
    return { data: {att1, att2, att3}, ...rest };
});

在此功能中,rest将保留除att1att2att3以外的对象中的所有属性。创建新对象时,添加...rest会将其他属性添加到结果对象中,因此,如果您有:

{
    att1: '1',
    att2: '2',
    att3: '3',
    subs: [...],
    other: 'other'
}

你会以这样的对象结束:

{
    data: {att1: '1', att2: '2', att3: '3'},
    subs: [...],
    other: 'other'
}

答案 2 :(得分:1)

您可以使用Array.prototype.map函数和递归来执行此操作:

public copyTree(originalTree: Array<object>): Array<object> {
  return originalTree.map(({ subs, ...data }: any) => ({
    data,
    subs: this.copyTree(subs)
  }));
}