从对象数组制作树,保留其他键值对

问题描述

问题

我有一个平面对象数组,我想将其变成嵌套树。我试过同时使用递归和减少,但还没有达到预期的效果

特别是我有数组:

const rawdata = [
  {name: "A",parent: "All",value: null},{name: "C",parent: "A",value: 10},{name: "D",value: 20},{name: "E",value: 30},{name: "B",{name: "F",parent: "B",{name: "G",{name: "H",value: 30}
]

想要的结果

我想把它变成:

let result = {name: "All",children: 
   [
     {name: "A",children: [
       {name: "C",],value: null,},children: [
       {name: "F",value: null
     }
   ]
  }

我尝试过的:

我已经能够使用递归创建一棵树,其中 All 使用 nameparent 值位于最顶层,但我无法弄清楚如何将 values 保留为对象的一部分。

let makeTree = (categories,parent) => {
  let node = {}
  categories
    .filter(c => c.parent === parent)
    .forEach(c => node[c.name] = 
      makeTree(categories,c.name))
  return node
}
console.log(JSON.stringify(makeTree(rawdata,"All")),null,2)

尝试应用这篇文章 Create an tree of objects from arrays 中的代码,但我的情况有点不同。任何帮助表示赞赏!

我也尝试使用:Build tree array from flat array in javascript

const nest = (items,id = null,link = 'parent_id') =>
  items
    .filter(item => item[link] === id)
    .map(item => ({ ...item,children: nest(items,item.id) }));
console.log(nest(rawdata,id = 'name',link = 'parent'))

但是也不能让它工作吗?

解决方法

我的提议...

const makeTree = arr =>
    arr.reduce((r,{name,parent,value,...others},i) =>
    {
    let refParent = r.pKeys.find(x=>x.name===parent)

    if (!refParent) // --> parent==='All'
      {
      r.res.name     = parent
      r.res.children = [] 
      refParent      = { name: parent,children: r.res.children }
      r.pKeys.push( refParent )
      }
    let newRow = {  name,...others }
    if (value===null) 
      {
      newRow.children = []
      r.pKeys.push( { name,children: newRow.children } )
      }
    refParent.children.push( newRow )

    if (i===r.end) return r.res
    return r
    },{ end:arr.length -1,res:{},pKeys:[] })
  ;


// show testing with 3 levels,and additinnal (optionnals) infos
const rawdata = 
  [ { name: 'A',parent: 'All',value: null },{ name: 'C',parent: 'A',value: 10   },{ name: 'D',value: 20,info1: 'ty',info2: 'zb' },{ name: 'E',value: 30,info1: 'kg',info2: 'zc' },{ name: 'B',{ name: 'F',parent: 'B',value: 10,info1: 'xyz' },{ name: 'G',{ name: 'H',info1: 'abc' },{ name: 'g1',parent: 'G',info1: 'gg1' },{ name: 'g2',info1: 'gg2' },{ name: 'g3',info1: 'ggg' } 
  ] 

let result = makeTree( rawdata )

console.log( result  )
.as-console-wrapper { max-height: 100% !important; top: 0; }

我就在它被归类为重复之前开始编写这个解决方案。 我只是在我准备好的代码副本的开头,但我在那里发现了 buggs,我删除了它:/ 当我想回来进行更正时,问题已被提交到重复项中。

也有一些不准确之处,我想确定我的代码的有效性。我还是个程序员,敲定代码的欲望更强烈。

我查看了重复的链接响应。我只看了一部分 30 个不同的答案

我的解决方案是唯一一个用简单而独特的 array.reduce() 做所有事情,并且不使用外部变量的解决方案。

这是我在这里重新激活我的答案的第二个原因。首先当然是将其呈现给 PO。