从对象数组制作树,保留其他键值对[重复]

Posted

技术标签:

【中文标题】从对象数组制作树,保留其他键值对[重复]【英文标题】:make tree from array of objects, keeping other key value pairs [duplicate] 【发布时间】:2020-12-20 02:15:18 【问题描述】:

问题

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

具体来说我有数组:

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

期望的结果

我想把它变成:

let result = name: "All",
  children: 
   [
     name: "A",
      children: [
       name: "C", value: 10,
       name: "D", value: 20,
       name: "E", value: 30,
      ],
      value: null,
     ,
     name: "B",
      children: [
       name: "F", value: 10,
       name: "G", value: 20,
       name: "H", value: 30,
      ],
      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'))

但也不能让它工作?

【问题讨论】:

是的,但我试图做一个简单的用例,可以推广到无限的父名关系 父母元素是否总是有value: null 是的@MisterJojo 对不起@MisterJojo,感谢您手动制作“所需输出”并将更新! 你会在这里找到我的答案,如下... 【参考方案1】:

我的提议...

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, value, ...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',  parent: 'A',   value: 20   , info1: 'ty', info2: 'zb' 
  ,  name: 'E',  parent: 'A',   value: 30   , info1: 'kg', info2: 'zc'   
  ,  name: 'B',  parent: 'All', value: null  
  ,  name: 'F',  parent: 'B',   value: 10   , info1: 'xyz'  
  ,  name: 'G',  parent: 'B',   value: null  
  ,  name: 'H',  parent: 'B',   value: 30   , info1: 'abc'  
  ,  name: 'g1', parent: 'G',   value: 20   , info1: 'gg1'  
  ,  name: 'g2', parent: 'G',   value: 20   , info1: 'gg2'  
  ,  name: 'g3', parent: 'G',   value: 20   , info1: 'ggg'  
  ] 

let result = makeTree( rawdata )

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

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

还有一些不准确之处,我想确定我的代码的有效性。我仍然是一名程序员,最终确定代码的愿望更强烈。

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

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

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

【讨论】:

非常感谢,这非常有用! @MayaGans 不客气,敲定这段代码是最强的,你的认可很好。

以上是关于从对象数组制作树,保留其他键值对[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何从键值对数组创建对象?

从 sql BigQuery 中的数组对象中获取键值对

怎样从对象中获取键值并保存在对象中

使用 Lodash 从键值对数组中创建对象

通过数组迭代设置对象键值对

如何在php中将对象数组转换为键值对