我有一个嵌套的对象数组,具有父子关系:
[
{
"id":"5b9ce8d51dbb85944baddfa5",
"name":"EARBANG",
"parent_id":0,
"status":"Inactive",
"children":[
{
"id":"5b9ce8d5d978f75e4b1584ba",
"name":"DIGINETIC",
"parent_id":"5b9ce8d51dbb85944baddfa5",
"status":"Active",
"children":[
{
"id":"5b9ce8d5cb79d63c8b38018c",
"name":"PREMIANT",
"parent_id":"5b9ce8d5d978f75e4b1584ba",
"status":"Active",
}
]
}
]
},
{
"id":"5b9ce8d51650fac75fa359c8",
"name":"GEEKOLOGY",
"parent_id":0,
"status":"Active",
},
{
"id":"5b9ce8d59f52e801a2e40a97",
"name":"TOYLETRY",
"parent_id":0,
"status":"Inactive",
},
{
"id":"5b9ce8d5d136fcfed2f3e0dd",
"name":"PAPRIKUT",
"parent_id":0,
"status":"Inactive",
},
{
"id":"5b9ce8d53afb7a61e188c48e",
"name":"EYERIS",
"parent_id":0,
"status":"Inactive",
}
]
我在这里想要
1-查找具有ID(例如)的对象5b9ce8d51dbb85944baddfa5
2-递归地迭代该对象的子级数组(如果不为空),并在数组中获取其所有子级,孙级和曾孙级的ID。
所以我的结果将是
{
"id":"5b9ce8d51dbb85944baddfa5",
childs: ["5b9ce8d5d978f75e4b1584ba", "5b9ce8d5cb79d63c8b38018c", ...]
}
我尝试了一些在堆栈溢出时可用的解决方案,但无法使其正常工作。
如果有人能帮助我,我的DS不够强大。
谢谢
答案 0 :(得分:1)
递归搜索ID。
#!/usr/bin/perl
use strict;
use warnings;
use Sample;
print Sample->test_function();
答案 1 :(得分:1)
您可以使用相当标准的递归方法来找到对象。边缘条件是传递给函数的对象是数组。这将进行深度优先搜索。
一旦找到对象,就需要获得后代子代。为了简单起见,我将其设为单独的功能:
0 0
如果找不到ID,它将返回undefined。
答案 2 :(得分:1)
看看我创建的递归搜索id的代码沙箱。找到ID后,它将调用另一个递归来生成child的数组。
console.log(findId(data, "5b9ce8d51dbb85944baddfa5"));
console.log(findId(data, "5b9ce8d5cb79d63c8b38018c"));
以下是上面两个的输出。
答案 3 :(得分:0)
let input = [
{
id: '5b9ce8d51dbb85944baddfa5',
name: 'EARBANG',
parent_id: 0,
status: 'Inactive',
children: [
{
id: '5b9ce8d5d978f75e4b1584ba',
name: 'DIGINETIC',
parent_id: '5b9ce8d51dbb85944baddfa5',
status: 'Active',
children: [
{
id: '5b9ce8d5cb79d63c8b38018c',
name: 'PREMIANT',
parent_id: '5b9ce8d5d978f75e4b1584ba',
status: 'Active'
}
]
}
]
},
{
id: '5b9ce8d51650fac75fa359c8',
name: 'GEEKOLOGY',
parent_id: 0,
status: 'Active'
},
{
id: '5b9ce8d59f52e801a2e40a97',
name: 'TOYLETRY',
parent_id: 0,
status: 'Inactive'
},
{
id: '5b9ce8d5d136fcfed2f3e0dd',
name: 'PAPRIKUT',
parent_id: 0,
status: 'Inactive'
},
{
id: '5b9ce8d53afb7a61e188c48e',
name: 'EYERIS',
parent_id: 0,
status: 'Inactive'
}
];
function getNestedChildrenId(fileteredObject, children) {
return fileteredObject.map(item => {
children.push(item.id);
if (item.children && item.children.length) {
getNestedChildrenId(item.children, children);
}
});
}
function getParentAndChildrenId(parentId, data) {
let result = { id: parentId, children: [] };
let fileteredParent = data.find(({ id }) => id === parentId);
if (fileteredParent.children) getNestedChildrenId(fileteredParent.children, result.children);
return result;
}
console.log(getParentAndChildrenId('5b9ce8d51dbb85944baddfa5', input));
console.log(getParentAndChildrenId('5b9ce8d5d136fcfed2f3e0dd', input));
答案 4 :(得分:0)
这是一个搜索递归函数:
function searchRecursive(data, id) {
let found = data.find(d => d.id === id);
if (!found) {
let i = 0;
while(!found && i < data.length) {
if (data[i].children && data[i].children.length) {
found = searchRecursive(data[i].children, id);
}
i++;
}
}
return found;
}
答案 5 :(得分:0)
这是一种基本的递归方法,
var data = [{
"id": "5b9ce8d51dbb85944baddfa5",
"name": "EARBANG",
"parent_id": 0,
"status": "Inactive",
"children": [{
"id": "5b9ce8d5d978f75e4b1584ba",
"name": "DIGINETIC",
"parent_id": "5b9ce8d51dbb85944baddfa5",
"status": "Active",
"children": [{
"id": "5b9ce8d5cb79d63c8b38018c",
"name": "PREMIANT",
"parent_id": "5b9ce8d5d978f75e4b1584ba",
"status": "Active",
}]
}]
}, {
"id": "5b9ce8d51650fac75fa359c8",
"name": "GEEKOLOGY",
"parent_id": 0,
"status": "Active",
}, {
"id": "5b9ce8d59f52e801a2e40a97",
"name": "TOYLETRY",
"parent_id": 0,
"status": "Inactive",
}, {
"id": "5b9ce8d5d136fcfed2f3e0dd",
"name": "PAPRIKUT",
"parent_id": 0,
"status": "Inactive",
}, {
"id": "5b9ce8d53afb7a61e188c48e",
"name": "EYERIS",
"parent_id": 0,
"status": "Inactive",
}];
function findChildren(obj, output, targetId, found) {
var _found;
obj.forEach((child) => {
if (found || child.id === targetId) {
if (found) output.push(child.id);
_found = true;
}
if (child.children && child.children.length) {
findChildren(child.children, output, targetId, _found);
}
});
return output;
}
var res = findChildren(data, [], "5b9ce8d51dbb85944baddfa5");
console.log('res:', res);
答案 6 :(得分:0)
这是一个通用的实现,一旦谓词函数返回true(希望我们可以在战利品中找到黄金),它就会停止递归:
var loot = {
box_a: 'seaweed',
box_b: {
box_c: [
{ box_d: 'tuna', box_e: ['gold', 'trash'] }
]
}
};
function descend_obj(item, pred_fn) {
if (item instanceof Array) {
return item.some(it => {
return descend_obj(it, pred_fn);
});
} else if (typeof item === "object") {
return Object.keys(item).some(k => {
return descend_obj(item[k], pred_fn);
});
} else {
return pred_fn(item);
}
}
let hasGold = descend_obj(loot, function isGold(item) {
return (item === 'gold')
});
let msg = (hasGold)
? 'yaaaay!'
: 'awwweee';
console.log(msg);//yaaaay!
答案 7 :(得分:0)
您可以使用这种方法:
var array = [your array];
function filter(array, id) {
result = {
id: id,
children: []
};
array.map(val => {
if (val.id == id) {
findChildren(val, result);
}
});
return result;
}
function findChildren(obj) {
if (obj.children && Array.isArray(obj.children)) {
obj.children.map(val => {
if (val.id) {
result.children.push(val.id);
}
if (val.children) {
findChildren(val);
}
});
}
}
var search = filter(array, '5b9ce8d51dbb85944baddfa5');
我认为代码很清楚,不需要解释。
答案 8 :(得分:0)
我倾向于不使用递归,因为递归更难于解释该循环,因为:
就同步代码而言,递归始终可以用循环代替。
这是非递归解决方案:
function findDescendants(data, key) {
let ancestor;
const ancestorStack = [data];
while (ancestorStack.length) { // 1- Find an object having id
const current = ancestorStack.pop();
for (const item of current) {
if (item.id === key) {
ancestor = item;
break;
}
const { children } = current;
if (children && children.length) {
ancestorStack.push(children);
}
}
}
const descendantIds = [];
const childrenStack = [ancestor.children];
while (childrenStack.length) { // 2- get id of all its descendants
const current = childrenStack.pop();
for (const item of current) {
descendantIds.push(item.id);
const { children } = item;
if (children && children.length) {
childrenStack.push(children);
}
}
}
return {
id: ancestor.id,
childs: descendantIds
}
}
实时演示:https://repl.it/@marzelin/findDescendants
由于此函数执行两项独立的任务,因此最好外包并概括这些任务:
function findDeep(predicate, deepProps, data)
function gatherDeep(prop, deepProps, data)
然后将findDecendants
简化为:
function findDescendants(data, key) {
const ancestor = findDeep(o => o.id === key, ["children"], data);
const descendantIds = gatherDeep("id", ["children"], ancestor.children);
return {
id: ancestor.id,
childs: descendantIds
}
}
答案 9 :(得分:0)
我使自己成为此功能,可能对您也有用。
当您不知道要处理哪种对象时,它会很有帮助...
示例:
var values = [
{
"id":"5b9ce8d51dbb85944baddfa5",
"name":"EARBANG",
"parent_id":0,
"status":"Inactive",
"children":[
{
"id":"5b9ce8d5d978f75e4b1584ba",
"name":"DIGINETIC",
"parent_id":"5b9ce8d51dbb85944baddfa5",
"status":"Active",
"children":[
{
"id":"5b9ce8d5cb79d63c8b38018c",
"name":"PREMIANT",
"parent_id":"5b9ce8d5d978f75e4b1584ba",
"status":"Active",
}
]
}
]
},
{
"id":"5b9ce8d51650fac75fa359c8",
"name":"GEEKOLOGY",
"parent_id":0,
"status":"Active",
},
{
"id":"5b9ce8d59f52e801a2e40a97",
"name":"TOYLETRY",
"parent_id":0,
"status":"Inactive",
},
{
"id":"5b9ce8d5d136fcfed2f3e0dd",
"name":"PAPRIKUT",
"parent_id":0,
"status":"Inactive",
},
{
"id":"5b9ce8d53afb7a61e188c48e",
"name":"EYERIS",
"parent_id":0,
"status":"Inactive",
}
]
//---------------------------------------------------------
// Strip Down to String Function
//----------------------------------------------------------
var depth = 0;
var stripdown = function(object, find, eol) {
depth = depth + 1;
var str = "";
var s = new function() {
return {
// Unique ID generator
id: new Date().getFullYear() +
new Date().getMonth() +
new Date().getDate() +
new Date().getHours() +
new Date().getMinutes() +
new Date().getSeconds() +
new Date().getMilliseconds(),
// Spaces for depth
space: ' ',
// Index
index: 0
}
};
while(s.index <= Object.keys(object).length){
// Every Last Line Has An Undefined Object So Clear Them
if (Object.keys(object)[s.index] != undefined) {
// If More Than 1 In The Line Add ',' + eol
if (s.index > 0) {
str = str + ',' + eol;
}
// Add Spaces For Each Depth Level
for(var i=0;i < depth;i++) { str = str + s.space; }
// Add Keys
str = str + Object.keys(object)[s.index] + ' : ';
// Add Values
if (typeof Object.values(object)[s.index] === 'object'){
str = str + '{' + eol; // Starting Tag
// Add Inner Object Values
str = str + stripdown(Object.values(object)[s.index], find, eol);
// Add Closing Space
for(var i=depth;i > 0;i--) { str = str + s.space; }
str = str + '}'; // Closing Tag
// Find Object
if(str.indexOf(find)>-1){
// Lower The Depth
depth = depth - 1;
return str + eol;
}
} else {
// No Sub Object
str = str + Object.values(object)[s.index];
}
}
// Next line
s.index = s.index + 1;
}
// Lower The Depth
depth = depth - 1;
// Return
return str + eol;
}
//---------------------------------------------------------
console.log(stripdown(values, "PREMIANT", "\n"));
用法:
stripdown( [object Object], SearchFor, "\n" );
将对象树作为字符串返回;
0 : {
id : 5b9ce8d51dbb85944baddfa5,
name : EARBANG,
parent_id : 0,
status : Inactive,
children : {
0 : {
id : 5b9ce8d5d978f75e4b1584ba,
name : DIGINETIC,
parent_id : 5b9ce8d51dbb85944baddfa5,
status : Active,
children : {
0 : {
id : 5b9ce8d5cb79d63c8b38018c,
name : PREMIANT,
parent_id : 5b9ce8d5d978f75e4b1584ba,
status : Active
}
}
}
}
}