如何使用Javascript从数组创建树(父子对象)

我有一个像这样的数组

[
"parent1|child1|subChild1","parent1|child1|subChild2","parent|child2|subChild1","parent1|child2|subChild2","parent2|child1|subChild1","parent2|child1|subChild2","parent2|child2|subChild1",.
.
.    
]

在我的第一个字符串之前|是父项,|之前的第二个字符串是孩子,第二个字符串之后的第三个字符串|是子孩子

如何将该数组转换为类似对象

[
 {
  "id": "parent1","children":[
   {
    "id": "child1","children":[
     {
      "id": "subChild1"
     }
    ]
   }
  ]
 }
]

父->子->子子对象

基于塞巴斯蒂安的答案,我在下面使用打字稿尝试了

private genTree(row) {
        let self = this;
        if (!row) {
            return;
        }
        const [parent,...children] = row.split('|');
        if (!children || children.length === 0) {
            return [{
                id: parent,children: []
            }];
        }
        return [{
            id: parent,children: self.genTree(children.join('|'))
        }];
    }

    private mergeDeep(children) {
        let self = this;
        const res = children.reduce((result,curr) => {
            const entry = curr;
            const existing = result.find((e) => e.id === entry.id);
            if (existing) {
                existing.children = [].concat(existing.children,entry.children);
            } else {
                result.push(entry);
            }
            return result;
        },[]);
        for (let i = 0; i < res.length; i++) {
            const entry = res[i];
            if (entry.children && entry.children.length > 0) {
                entry.children = self.mergeDeep(entry.children);
            }
        };
        return res;
    }

private constructTree(statKeyNames){
    let self = this;
    const res = this.mergeDeep(statKeyNames.map(self.genTree).map(([e]) => e));
    console.log(res);
}

但这给了我“无法读取未定义的属性'genTree'”错误

更新:

根据塞巴斯蒂安的评论,将self.genTree更改为this.genTree.bind(this),并且没有任何问题

luvlu 回答:如何使用Javascript从数组创建树(父子对象)

您必须为此使用递归。在这里看看:

const arr = [
  "parent1|child1|subChild1","parent1|child1|subChild2","parent|child2|subChild1","parent1|child2|subChild2","parent2|child1|subChild1","parent2|child1|subChild2","parent2|child2|subChild1"
];

function genTree(row) {

  const [parent,...children] = row.split('|');

  if (!children || children.length === 0) {
    return [{
      id: parent,children: []
    }];
  }

  return [{
    id: parent,children: genTree(children.join('|'))
  }];
};

function mergeDeep(children) {

  const res = children.reduce((result,curr) => {

    const entry = curr;

    const existing = result.find((e) => e.id === entry.id);
    if (existing) {

      existing.children = [].concat(existing.children,entry.children);
    } else {
      result.push(entry);
    }

    return result;
  },[]);

  for (let i = 0; i < res.length; i++) {

    const entry = res[i];
    if (entry.children && entry.children.length > 0) {
      entry.children = mergeDeep(entry.children);
    }
  };

  return res;
}

const res = mergeDeep(arr.map(genTree).map(([e]) => e));
console.log(JSON.stringify(res,false,2));

我在这里使用了两个助手:genTree(row)从每一行递归地生成一棵简单的树,而mergeDeep(children)则在arr.map(genTree).map(([e]) => e)的结果中减少第一级树,然后进行迭代在数组上递归地对每个条目的所有children执行相同的操作。

,

您可以使用将每个对象映射到其唯一路径的mapper对象(您可以将每个id映射到该对象,但是id在这里不是唯一的)。然后reduce数组中的每个子项。将root对象设置为 initialValue 。累加器将是当前项目的父对象。在每次迭代中返回当前对象。

const input = [
    "parent1|child1|subChild1","parent1|child2|subChild1","parent2|child2|subChild1"
  ],mapper = {},root = { children: [] }

for (const str of input) {
  let splits = str.split('|'),path = '';

  splits.reduce((parent,id,i) => {
    path += `${id}|`;

    if (!mapper[path]) {
      const o = { id };
      mapper[path] = o; // set the new object with unique path
      parent.children = parent.children || [];
      parent.children.push(o)
    }
    
    return mapper[path];
  },root)
}

console.log(root.children)

本文链接:https://www.f2er.com/3146913.html

大家都在问