如何递归遍历具有 child 数组和 return 最终转换的 objects 数组的对象数组
How to recursively go through an array of ojects with child arrays and return a final transformed array of objects
我希望遍历一个 object,它也可以有 object 的数组,也可以有 object 的数组,等等。理论上这个结构可以是无限的,但它不太可能超过 12 层。
转换前的数据结构示例:
{
id: '1234',
name: 'item 1',
children: [
{
id: '2345',
name: 'item 2',
// other properties that I don't care about will be here too
children: [
{
id: '3456',
name: 'item 3',
children: [
{
id: '4567',
name: 'item 4',
}
],
}
],
}
],
}
我需要什么样的最终数据结构(首先需要一个默认值object):
const someArray = [
{
// this first child is static and will always be here after transform
title: 'Projects'
key: 'projects',
children: [
{
title: 'item 1', // this is 'name' property
key: '1234,' // this is 'id' property
children: [
{
title: 'item 2',
key: '2345',
children: [
// continue as long as there are children arrays
]
}
]
}
]
}
]
我尝试了几种不同的解决方案,我相信递归函数是解决这个问题的方法,但我就是无法弄清楚如何输出最终结构。我得到了最后两个children,但我无法累积前面的children。
这是我得到的最接近的 non-working 解决方案:
const startingObj = [
{
title: 'Projects',
key: 'projects',
}
]
function buildTree (obj) {
// check if we have a children array with at least 1 child.
if (obj?.children?.length) {
return obj?.children.reduce((a, item) => {
if (a) return {
...item.children,
title: a.name || a.title,
key: a.id || a.key,
};
if (item?.children?.length) return buildTree(item.children);
}, obj);
}
}
buildTree(); // would pass in the sample data structure from above here.
我不确定 reduce 是否不是这里的最佳解决方案,或者我只是从我的方法中遗漏了一些关键思想。任何帮助将不胜感激。谢谢。
这个怎么样:
// this function recurses down the tree and for each item it makes a
// transformed item (saving only the title and key). Then the transformed
// item is returned and the caller pushes it into the children array
function buildtree(obj) {
let item = {
title: obj.name || obj.title,
key: obj.id || obj.key,
children: []
}
if (obj.children)
for (child of obj.children)
item.children.push( buildtree(child) )
return item;
}
let result = [
{
title: 'Projects',
key: 'projects',
children: []
}
]
result[0].children.push( buildtree(obj) )
这是一个完整的可运行示例:
obj = {
id: '1234',
name: 'item 1',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '2345',
name: 'item 2',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '3456',
name: 'item 3',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '4567',
name: 'item 4',
x: '', // other properties that I don't care about will be here too
},
{
id: '5678',
name: 'item 5',
x: '', // other properties that I don't care about will be here too
}
]
},
{
id: '6789',
name: 'item 6',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '7890',
name: 'item 7',
x: '', // other properties that I don't care about will be here too
},
{
id: '890a',
name: 'item 8',
x: '', // other properties that I don't care about will be here too
}
]
}
]
},
{
id: '90ab',
name: 'item 9',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '0abc',
name: 'item 10',
x: '', // other properties that I don't care about will be here too
children: [
{
id: 'abcd',
name: 'item 11',
x: '', // other properties that I don't care about will be here too
},
{
id: 'bcde',
name: 'item 12',
x: '', // other properties that I don't care about will be here too
}
]
},
{
id: 'cdef',
name: 'item 13',
x: '', // other properties that I don't care about will be here too
children: [
{
id: 'defg',
name: 'item 14',
x: '', // other properties that I don't care about will be here too
},
{
id: 'efgh',
name: 'item 15',
x: '', // other properties that I don't care about will be here too
}
]
}
]
}
]
}
console.log( JSON.stringify(obj) )
function buildtree(obj) {
let item = {
title: obj.name || obj.title,
key: obj.id || obj.key,
children: []
}
if (obj.children)
for (child of obj.children)
item.children.push( buildtree(child) )
return item;
}
let result = [
{
title: 'Projects',
key: 'projects',
children: []
}
]
result[0].children.push( buildtree(obj) )
console.log( JSON.stringify(result) )
因此,如果我没看错的话,您只需要遍历所有对象并将每个对象的 'id' 键更改为 'key' 并将 'name' 键更改为 'title'。这是一个递归解决方案:
function recursiveArray(arr) {
return arr.map(e => ({
key: e.id,
title: e.name,
children: e.children.length ? recursiveArray(e.children) : []
}));
}
function changeKeysOfNestedObject(obj) {
return {
key: obj.id,
title: obj.name,
children: obj.children.length ? recursiveArray(obj.children) : []
};
}
//test case
console.log(changeKeysOfNestedObject({
id: '1234',
name: 'item 1',
children: [
{
id: '2345',
name: 'item 2',
children: [
{
id: '3456',
name: 'item 3',
children: [
{
id: '4567',
name: 'item 4',
children: []
}
],
}
],
}
],
}));
我希望遍历一个 object,它也可以有 object 的数组,也可以有 object 的数组,等等。理论上这个结构可以是无限的,但它不太可能超过 12 层。
转换前的数据结构示例:
{
id: '1234',
name: 'item 1',
children: [
{
id: '2345',
name: 'item 2',
// other properties that I don't care about will be here too
children: [
{
id: '3456',
name: 'item 3',
children: [
{
id: '4567',
name: 'item 4',
}
],
}
],
}
],
}
我需要什么样的最终数据结构(首先需要一个默认值object):
const someArray = [
{
// this first child is static and will always be here after transform
title: 'Projects'
key: 'projects',
children: [
{
title: 'item 1', // this is 'name' property
key: '1234,' // this is 'id' property
children: [
{
title: 'item 2',
key: '2345',
children: [
// continue as long as there are children arrays
]
}
]
}
]
}
]
我尝试了几种不同的解决方案,我相信递归函数是解决这个问题的方法,但我就是无法弄清楚如何输出最终结构。我得到了最后两个children,但我无法累积前面的children。
这是我得到的最接近的 non-working 解决方案:
const startingObj = [
{
title: 'Projects',
key: 'projects',
}
]
function buildTree (obj) {
// check if we have a children array with at least 1 child.
if (obj?.children?.length) {
return obj?.children.reduce((a, item) => {
if (a) return {
...item.children,
title: a.name || a.title,
key: a.id || a.key,
};
if (item?.children?.length) return buildTree(item.children);
}, obj);
}
}
buildTree(); // would pass in the sample data structure from above here.
我不确定 reduce 是否不是这里的最佳解决方案,或者我只是从我的方法中遗漏了一些关键思想。任何帮助将不胜感激。谢谢。
这个怎么样:
// this function recurses down the tree and for each item it makes a
// transformed item (saving only the title and key). Then the transformed
// item is returned and the caller pushes it into the children array
function buildtree(obj) {
let item = {
title: obj.name || obj.title,
key: obj.id || obj.key,
children: []
}
if (obj.children)
for (child of obj.children)
item.children.push( buildtree(child) )
return item;
}
let result = [
{
title: 'Projects',
key: 'projects',
children: []
}
]
result[0].children.push( buildtree(obj) )
这是一个完整的可运行示例:
obj = {
id: '1234',
name: 'item 1',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '2345',
name: 'item 2',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '3456',
name: 'item 3',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '4567',
name: 'item 4',
x: '', // other properties that I don't care about will be here too
},
{
id: '5678',
name: 'item 5',
x: '', // other properties that I don't care about will be here too
}
]
},
{
id: '6789',
name: 'item 6',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '7890',
name: 'item 7',
x: '', // other properties that I don't care about will be here too
},
{
id: '890a',
name: 'item 8',
x: '', // other properties that I don't care about will be here too
}
]
}
]
},
{
id: '90ab',
name: 'item 9',
x: '', // other properties that I don't care about will be here too
children: [
{
id: '0abc',
name: 'item 10',
x: '', // other properties that I don't care about will be here too
children: [
{
id: 'abcd',
name: 'item 11',
x: '', // other properties that I don't care about will be here too
},
{
id: 'bcde',
name: 'item 12',
x: '', // other properties that I don't care about will be here too
}
]
},
{
id: 'cdef',
name: 'item 13',
x: '', // other properties that I don't care about will be here too
children: [
{
id: 'defg',
name: 'item 14',
x: '', // other properties that I don't care about will be here too
},
{
id: 'efgh',
name: 'item 15',
x: '', // other properties that I don't care about will be here too
}
]
}
]
}
]
}
console.log( JSON.stringify(obj) )
function buildtree(obj) {
let item = {
title: obj.name || obj.title,
key: obj.id || obj.key,
children: []
}
if (obj.children)
for (child of obj.children)
item.children.push( buildtree(child) )
return item;
}
let result = [
{
title: 'Projects',
key: 'projects',
children: []
}
]
result[0].children.push( buildtree(obj) )
console.log( JSON.stringify(result) )
因此,如果我没看错的话,您只需要遍历所有对象并将每个对象的 'id' 键更改为 'key' 并将 'name' 键更改为 'title'。这是一个递归解决方案:
function recursiveArray(arr) {
return arr.map(e => ({
key: e.id,
title: e.name,
children: e.children.length ? recursiveArray(e.children) : []
}));
}
function changeKeysOfNestedObject(obj) {
return {
key: obj.id,
title: obj.name,
children: obj.children.length ? recursiveArray(obj.children) : []
};
}
//test case
console.log(changeKeysOfNestedObject({
id: '1234',
name: 'item 1',
children: [
{
id: '2345',
name: 'item 2',
children: [
{
id: '3456',
name: 'item 3',
children: [
{
id: '4567',
name: 'item 4',
children: []
}
],
}
],
}
],
}));