如何从嵌套的对象数组中获取每个父级的值
Posted
技术标签:
【中文标题】如何从嵌套的对象数组中获取每个父级的值【英文标题】:How to get the value of each parent from a nested array of object 【发布时间】:2021-10-27 11:43:55 【问题描述】:所以我有多个对象数组,每个对象都包含一个子对象。
例如
const data = [
id: 1,
name: 'parent 1',
children: [
id: 'c1',
name: 'child 1',
children: [
id: 'g1',
name: 'grand 1',
children: [],
,
],
,
],
,
id: 2,
name: 'parent 2',
children: [
id: 2,
name: 'c1',
children: [],
,
],
,
id: 3, name: 'parent 3', children: [] ,
];
我想要发生的是,如果我正在搜索的 Id 是 'g1',我会得到结果
const result = ['parent 1', 'c1', 'grand 1']
循环只会停止并获取它通过的所有名称,直到满足条件(在本例中为 id)
当前方法已完成
/**
* Details
* @param id the value you are searching for
* @param items nested array of object that has child
* @param key name of the value you are looking for
* @returns string of array that matches the id
* @example ['parent 1', 'c1', 'grand 1']
*/
export function findAll(id: string, items: any, key: string): string[]
let i = 0;
let found;
let result = [];
for (; i < items.length; i++)
if (items[i].id === id)
result.push(items[i][key]);
else if (_.isArray(items[i].children))
found = findAll(id, items[i].children, key);
if (found.length)
result = result.concat(found);
return result;
【问题讨论】:
你试过什么?另外,const result = 'parent 1' > 'c1' > 'grand 1'
这是无效的数据对象,你可以验证你想要什么数据结构。
@ikhvjs,我更新了我想看的结果,谢谢评论
到目前为止你尝试过什么?我认为递归函数方法适合您的情况。
@ikhvjs,我尝试了这个,第三个答案,***.com/questions/30714938/… 并进行了一些修改,但我似乎找不到将父母姓名存储在结果数组中的方法
你能告诉我们你的方法吗?
【参考方案1】:
我编写了这段迭代代码,可能会对您有所帮助。它基本上遍历存储从顶层到所需id的路径的结构:
function getPath(obj, id)
// We need to store path
// Start stack with root nodes
let stack = obj.map(item => (path: [item.name], currObj: item));
while (stack.length)
const path, currObj = stack.pop()
if (currObj.id === id)
return path;
else if (currObj.children?.length)
stack = stack.concat(currObj.children.map(item => (path: path.concat(item.name), currObj: item)));
return null; // if id does not exists
此代码假定您的结构是正确的并且没有遗漏任何部分(除了可以为 null 的子代)。
顺便说一句,你的答案正确吗?我想路径应该是:
["parent 1", "child 1", "grand 1"]
【讨论】:
【参考方案2】:下面的解决方案是执行搜索的递归函数。
const data = [
id: 1,
name: 'parent 1',
children: [
id: 'c1',
name: 'child 1',
children: [
id: 'g1',
name: 'grand 1',
children: [],
,
],
,
],
,
id: 2,
name: 'parent 2',
children: [
id: 2,
name: 'c1',
,
],
,
id: 3, name: 'parent 3', children: [] ,
];
function getPath(object, search)
if (object.id === search) return [object.name];
else if ((object.children) || Array.isArray(object))
let children = Array.isArray(object) ? object : object.children;
for (let child of children)
let result = getPath(child, search);
if (result)
if (object.id )result.unshift(object.name);
return result;
//const result = ['parent 1', 'c1', 'grand 1']
const result = getPath(data, 'g1');
console.log(result);
【讨论】:
嗨 Lajos,当数据结构中只有一个“g1”时,它工作正常。如果在另一组 JSON 中的最后一个子节点中存在相同的“g1”怎么办。我的数据结构中没有名为 id 的单独键。我可能有重复的数据。现在如何提取我想要的确切数据集。? @JohnsonAnthony 我对您的问题的理解是您有一个没有id
的 JSON,并且您可能有重复的结果。如果我正确理解您的问题,那么您想找到所有匹配项。这是一个准确的理解吗?另外,您可以创建一个 JSFiddle 并在评论部分分享链接,或者提出一个单独的问题并在评论部分分享链接?如果您今天创建它,那么我可能会在今天或明天研究它。【参考方案3】:
您可以编写一个递归函数,在将遍历的对象累积到堆栈中时遍历数组。一旦你得到一个带有你想要(id == g1)
的 id 的对象,你就可以打印解决方案。可能是这样的:
'use strict';
function print(stack)
//console.log("Printing result...\n");
let result = "";
stack.forEach(element =>
result += element["name"] + " > ";
);
console.log(result + "\n");
function walkThrough(data, id, stack)
if (data !== undefined)
for (let i = 0; i < data.length; i++)
const element = data[i];
//console.log("Going through " + element["name"] + " with id == " + element["id"]);
stack.push(element);
if (element["id"] == id) print(stack);
else walkThrough(element["children"], id, stack);
const data = [
"id": 1,
"name": 'parent 1',
"children": [
"id": 'c1',
"name": 'child 1',
"children": [
"id": 'g1',
"name": 'grand 1',
"children": [],
,
],
,
],
,
"id": 2,
"name": 'parent 2',
"children": [
"id": 2,
"name": 'c1',
,
],
,
"id": 3, "name": 'parent 3', "children": [] ,
];
//Calling the function to walk through the array...
walkThrough(data, 'g1', []);
【讨论】:
【参考方案4】:另一种方法(不像上述解决方案那么优雅,但也可以)
非常直接:
使用for
迭代循环到第 3 级,当在第 3 级找到孙子时,break
以逃避所有 3 级。
我很好奇不同的解决方案如何比较大型数据集(比如一百万条记录)的性能。
let i=0, k=0, l=0;
let childrenLength = 0, grandChildrenLength = 0;
let result = [];
let foundGrandChild = false;
function searchGrandChild(searchString)
for (i; i< data.length; ++i)
if(data.length > 0)
childrenLength = data[i].children.length;
if(childrenLength > 0)
for (k; k < childrenLength; ++k)
if(data[i].children[k] != undefined)
grandChildrenLength = data[i].children[k].children.length;
if(grandChildrenLength > 0)
for (l; l < grandChildrenLength; ++l)
if(data[i].children[k].children[l] != undefined)
if(data[i].children[k].children[l].id === searchString)
result.push(data[i].name);
result.push(data[i].children[k].id);
result.push(data[i].children[k].children[l].name);
foundGrandChild = true;
console.log('Yap, we found your grandchild ?')
console.log(result);
break;
if(foundGrandChild) break;
if(foundGrandChild) break;
if(foundGrandChild) break;
if(!foundGrandChild) console.log('sorry, we could not find your grandchild ?')
;
const data = [
id: 1,
name: 'parent 1',
children: [
id: 'c1',
name: 'child 1',
children: [
id: 'g1',
name: 'grand 1',
children: [],
,
],
,
],
,
id: 2,
name: 'parent 2',
children: [
id: 2,
name: 'c1',
,
],
,
id: 3, name: 'parent 3', children: [] ,
];
console.log('Let us search for "g1" ...');
searchGrandChild('g1');
console.log('Let us now search for "g2" ...');
foundGrandChild = false;
searchGrandChild('g2');
【讨论】:
以上是关于如何从嵌套的对象数组中获取每个父级的值的主要内容,如果未能解决你的问题,请参考以下文章