Reputation: 483
I am trying java script recursive function that return an array of values based on the key.
The nested JavaScript object has unknown depth. The function is working but the value are not returning properly ..I am getting only first iterated value while I am calling this recursive function from another function. But I can able to console and see the values in same function.
Here is My json
{
"id": 0,
"name": "Root Entity",
"children": [{
"id": 1,
"name": "REAT",
"children": [{
"id": 2,
"name": "Business",
"children": [{
"id": 3,
"name": "Region 1",
"children": [{
"id": 5,
"name": "Area 1",
"children": [
{
"dealerId": 14,
"name": "lead 1"
},
{
"dealerId": 15,
"name": "lead 2"
},
{
"dealerId": 16,
"name": "lead 3"
},
{
"dealerId": 17,
"name": "lead 4"
},
{
"dealerId": 18,
"name": "lead 5"
},
{
"dealerId": 19,
"name": "lead 6"
}, {
"dealerId": 20,
"name": "lead 7"
}],
"kpi_1_met": 0,
"lead_num": 0,
}, {
"id": 6,
"name": "Area 2",
"children": [{
"dealerId": 31
"name": "lead 1"
}]
}]
}]
}]
}]
}
Here is the recursion function I have tried
async function outputArray(output, leadInfo, req, res) {
let resoutput = output.children,
constructedArray = [],
obj = {};
// dealerName, entityList = await entityNames(req, res);
let leagueData = [];
resoutput.forEach((dataArray) => {
if (dataArray.hasOwnProperty('children') &&
dataArray.children instanceof Array &&
dataArray.children.length > 0) {
// console.log("================ dataArray.children", dataArray.children[0]['name']);
for (let i in dataArray.children) {
obj = { 'regionId': dataArray.children[i].id, 'region': dataArray.children[i].name};
outputArray(dataArray.children[i], leadInfo, req, res);
leagueData.push(obj);
// console.log("================ leagueData ===============", leagueData);
}
} else {
if (dataArray.hasOwnProperty('name'))
// console.log("================ else", dataArray.name);
}
});
// console.log("================ leagueData outside =============", leagueData);
return leagueData;
}
And I am calling the above recursive function in another function that is below
async function dataTable(output, leadInfo, req, res) {
let obj = {},
data = await outputArray(output, leadInfo, req, res, obj);
// here First Iterated data only coming
// console.log("data from data Table", data)
}
Output Should be
[
{ regionId: 3, areaId: 5, dealerId: 14, name: 'lead 1', region: 'Region 1', area: 'Area 1' },
{ regionId: 3, areaId: 5, dealerId: 31, name: 'lead 1', region: 'Region 1', area: 'Area 2' }
]
It should be populated based on the hierarchy of the tree
Kindly anyone please help me on this. I am trying hard to get it out.
Upvotes: 0
Views: 865
Reputation: 50807
It's not entirely clear to me if this is what you're looking for, but here is a technique that will flatten out the hierarchy, compressing ancestor name/ids into properties of the leaf nodes:
const nameToKey = (name) =>
name .replace(/\s*\d+$/, '') .toLowerCase ()
const flattenHierarchy = (node, desc = {}, {name, id, children} = node) =>
children && children .length > 0
? children .flatMap (child => flattenHierarchy (child, {
...desc,
[nameToKey (name)]: name,
[nameToKey (name) + 'Id']: id
}))
: [{...desc, ...node}]
const data = {"children": [{"children": [{"children": [{"children": [{"children": [{"dealerId": 14, "name": "lead 1"}, {"dealerId": 15, "name": "lead 2"}, {"dealerId": 16, "name": "lead 3"}, {"dealerId": 17, "name": "lead 4"}, {"dealerId": 18, "name": "lead 5"}, {"dealerId": 19, "name": "lead 6"}, {"dealerId": 20, "name": "lead 7"}], "id": 5, "kpi_1_met": 0, "lead_num": 0, "name": "Area 1"}, {"children": [{"dealerId": 31, "name": "lead 1"}], "id": 6, "name": "Area 2"}], "id": 3, "name": "Region 1"}], "id": 2, "name": "Business"}], "id": 1, "name": "REAT"}], "id": 0, "name": "Root Entity"}
console .log (flattenHierarchy (data))
This generates an array of objects that look like this:
{
"root entity": "Root Entity",
"root entityId": 0,
"reat": "REAT",
"reatId": 1,
"business": "Business",
"businessId": 2,
"region": "Region 1",
"regionId": 3,
"area": "Area 1",
"areaId": 5,
"dealerId": 14,
"name": "lead 1"
}
In the base case, when we're at a leaf node in the children -> children -> children
hierarchy, we return the object we've built up with all of the leaf node's properties appended to it. If we're not on a leaf, then we append the current name/id property to our working object, and recursively call the function on each child using this enhanced working object, then flatMap
their results into a single array.
This does not entirely match your suggested output. Firstly, there are more results, one for each leaf node in your input. I'm guessing that this is fine, that you were just providing samples and not the full expected result. If not, by what criteria do you choose the nodes to return? Secondly, there are several additional properties from the hierarchy included here, things like reatId
and root entity
. If you don't want these in the output, how do you decide to exclude them?
Finally, although I took a stab at converting the names into useful keys, it's guesswork, and it feels off. Transforming a string data value to an object key worries me; but perhaps it's just what you want.
Upvotes: 0
Reputation: 966
I am not sure I get the question correctly. If you just want to iterate in the data and push that to an array the below code will help.
<script>
var data = {
"id": 0,
"name": "Root Entity",
"children": [{
"id": 1,
"name": "REAT",
"children": [{
"id": 2,
"name": "Business",
"children": [{
"id": 3,
"name": "Region 1",
"children": [{
"id": 5,
"name": "Area 1",
"children": [
{
"id": 14,
"name": "lead 1"
},
{
"id": 15,
"name": "lead 2"
},
{
"id": 16,
"name": "lead 3"
},
{
"id": 17,
"name": "lead 4"
},
{
"id": 18,
"name": "lead 5"
},
{
"id": 19,
"name": "lead 6"
}, {
"id": 20,
"name": "lead 7"
}],
"kpi_1_met": 0,
"lead_num": 0
}, {
"id": 6,
"name": "Area 2",
"children": [{
"id": 31,
"name": "lead 1"
}]
}]
}]
}]
}]
}
let leagueData = [];
function outputArray(output, leadInfo, req, res) {
let resoutput = output.children,
obj = { 'regionId': output.id, 'region': output.name};
leagueData.push(obj);
if (output.hasOwnProperty('children') &&
output.children instanceof Array &&
output.children.length > 0) {
for (let i in output.children) {
console.log("*************** leagueData ===============", output.children[i]);
outputArray(output.children[i], leadInfo, req, res);
}
}
}
function dataTable(output, leadInfo, req, res) {
let obj = {},
data = outputArray(output, leadInfo, req, res, obj);
// here First Iterated data only coming
console.log("data from data Table", leagueData)
}
dataTable(data,"","","");
</script>
Upvotes: 0
Reputation: 493
This is might you are looking for
let a = {
"id": 0,
"name": "Root Entity",
"children": [{
"id": 1,
"name": "REAT",
"children": [{
"id": 2,
"name": "Business",
"children": [{
"id": 3,
"name": "Region 1",
"children": [{
"id": 5,
"name": "Area 1",
"children": [
{
"id": 14,
"name": "lead 1"
},
{
"id": 15,
"name": "lead 2"
},
{
"id": 16,
"name": "lead 3"
},
{
"id": 17,
"name": "lead 4"
},
{
"id": 18,
"name": "lead 5"
},
{
"id": 19,
"name": "lead 6"
}, {
"id": 20,
"name": "lead 7"
}],
"kpi_1_met": 0,
"lead_num": 0,
}, {
"id": 6,
"name": "Area 2",
"children": [{
"id": 31,
"name": "lead 1"
}]
}]
}]
}]
}]
}
function test(data) {
let response = [];
if (Array.isArray(data)) {
for (let o of data) {
response.push({ id: o.id, name: o.name });
if (o.hasOwnProperty('children') && o.children.length > 0) {
let child = test(o.children);
response = response.concat(child);
}
}
} else {
response.push({ id: data.id, name: data.name });
if (data.hasOwnProperty('children') && data.children.length > 0) {
let child = test(data.children);
response = response.concat(child);
}
}
return response;
}
let res = test(a);
console.log(res)
Upvotes: 1
Reputation: 1044
You should save result of recursive call
outputArray(dataArray.children[i], leadInfo, req, res);
Upvotes: 0