How to fetch parent ids recursively from json strings - javascript

{
"id": "1",
"name": "root",
"children": [
{
"id": "1.1",
"name": "Child 1",
"children": [
{
"id": "1.1.1",
"name": "Child 1-1",
"children": [
{
"id": "1-1-1",
"name": "Child 1-1-1",
"children": [
]
}
]
},
{
"id": "1.1.2",
"name": "Child 1-2",
"children": [
]
},
{
"id": "1.1.3",
"name": "Child 1-3",
"children": [
]
}
]
},
{
"id": "1.2",
"name": "Child 2",
"children": [
{
"id": "1.2.1",
"name": "Child 2-2",
"children": [
]
}
]
}
]
}
This is the JSON string as the response. Had to fetch for the parent elements recursively all the parents id.
For instance, input is 1.2.1 then it returns [1.2]
input is 1.1.3 then it returns [1.1, 1]
How can I achieve this?

Just a simple recursion using dfs
const data = JSON.parse('{"id":"1","name":"root","children":[{"id":"1.1","name":"Child 1","children":[{"id":"1.1.1","name":"Child 1-1","children":[{"id":"1-1-1","name":"Child 1-1-1","children":[]}]},{"id":"1.1.2","name":"Child 1-2","children":[]},{"id":"1.1.3","name":"Child 1-3","children":[]}]},{"id":"1.2","name":"Child 2","children":[{"id":"1.2.1","name":"Child 2-2","children":[]}]}]}')
function dfs (target, node) {
if (node.id === target) { return node.id }
if (!node.children) { return false } // we could even skip that line since in your data you seem to have an empty array
const has = node.children.find(c => dfs(target, c))
return has && [node.id].concat(has.id)
}
console.log(dfs('1.2.1', data))
console.log(dfs('1.1.3', data))

You could take an iterative and recursive approach and
chcek if the given data is not an object, then return
check for the id and if found return an empty array, which gets filled by the calling function
iterate children with a short circuit on found and call the function again.
function getParentIds(object, id) {
var ids;
if (!object || typeof object !== 'object') return; // no object
if (object.id === id) return []; // id found
return object.children.some(o => ids = getParentIds(o, id)) // call recursive function
? [...ids, object.id] // if found, take ids
: undefined; // otherwise return falsy
}
var data = { id: "1", name: "root", children: [{ id: "1.1", name: "Child 1", children: [{ id: "1.1.1", name: "Child 1-1", children: [{ id: "1-1-1", name: "Child 1-1-1", children: [] }] }, { id: "1.1.2", name: "Child 1-2", children: [] }, { id: "1.1.3", name: "Child 1-3", children: [] }] }, { id: "1.2", name: "Child 2", children: [{ id: "1.2.1", name: "Child 2-2", children: [] }] }] };
console.log(getParentIds(data, '1.2.1')); // ['1.2']
console.log(getParentIds(data, '1.1.3')); // ['1.1', '1']
console.log(getParentIds(data, 'foo')); // undefined
.as-console-wrapper { max-height: 100% !important; top: 0; }

You would have to parse the complete object to recursively inject the parent ids in child objects. Something like this will do the thing.
function injectParents(data, parents) {
if(!parents) {
parents = [];
}
parents.push(data.id);
data.children.map(child=>{
child.parents = parents;
if(child.children && child.children.length>0) {
child = injectParents(child, Array.from(parents));
}
return child;
});
return data;
}
Then you would normally call it like
const injectedResponse = injectParents(response, null);

you can use
for(let x in arrayName){
//here you can access the json
console.log(arayName(x).id)
}

Is this what are you looking for?
//Input
let input = '1.2.1';
//Data
data = JSON.parse('{"id":"1","name":"root","children":[{"id":"1.1","name":"Child 1","children":[{"id":"1.1.1","name":"Child 1-1","children":[{"id":"1-1-1","name":"Child 1-1-1","children":[]}]},{"id":"1.1.2","name":"Child 1-2","children":[]},{"id":"1.1.3","name":"Child 1-3","children":[]}]},{"id":"1.2","name":"Child 2","children":[{"id":"1.2.1","name":"Child 2-2","children":[]}]}]}')
//Main function start here
function findIdWhereChild(data, input) {
if (data.children?.find(x => x.id == input)) {
return data.id;
}
else {
if (data.children.length > 0) {
for (let i = 0; i < data.children.length; i++) {
let findalResult = findIdWhereChild(data.children[i], input);
if (findalResult) {
return findalResult;
};
};
} else {
return undefined;
}
}
};
//Execution LOGs
console.log(findIdWhereChild(data, input));

Related

Form a nested tree from an array of objects in javascript

So there is array of objects of below format
let inputs = [
{
"id": "614344d9d9c21c0001e6af2e",
"groupName": "Unassigned",
"parentGroup": "null"
},
{
"id": "614447da152f69c3c1d52f2e",
"groupName": "P1",
"parentGroup": "null"
},
{
"id": "614447da152f69c3c1d52f38",
"groupName": "K1",
"parentGroup": "C1"
},
{
"id": "614447da152f69c3c1d52f3e",
"groupName": "A2",
"parentGroup": "C2"
},
{
"id": "614447da152f69c3c1d52f40",
"groupName": "G1",
"parentGroup": "P2"
},
{
"id": "614447da152f69c3c1d52f46",
"groupName": "F1",
"parentGroup": "null"
},
{
"id": "614447da152f69c3c1d52f30",
"groupName": "P2",
"parentGroup": "null"
},
{
"id": "614447da152f69c3c1d52f36",
"groupName": "C2",
"parentGroup": "P1"
},
{
"id": "614447da152f69c3c1d52f3c",
"groupName": "A1",
"parentGroup": "C2"
},
{
"id": "614447da152f69c3c1d52f34",
"groupName": "C1",
"parentGroup": "P1"
},
{
"id": "614447da152f69c3c1d52f32",
"groupName": "P3",
"parentGroup": "null"
},
{
"id": "614447da152f69c3c1d52f3a",
"groupName": "K2",
"parentGroup": "C1"
},
{
"id": "614447da152f69c3c1d52f42",
"groupName": "GG1",
"parentGroup": "G1"
},
{
"id": "614447da152f69c3c1d52f44",
"groupName": "GGG1",
"parentGroup": "GG1"
}
]
i am trying to create a tree structure of format
{name:'p1',children:[{name:'c1':children:[]}]}
so i sorted all the elements of given array considering element with parentGroup as "null" to be at the top of the array.
let finalArr = [];
inputs.sort((a,b)=> (a.parentGroup === "null") ? -1 : 1);
And for each element of the inputs array, i was iterating below logic
inputs.forEach(ele => {
if(ele.parentGroup === "null"){
let child= {name:ele.groupName,children:[]};
finalArr.push(child);
}else{
finalArr.forEach(item => {
this.findNode(item,ele);
})
}
});
If the 'parentGroup' of element is "null", then create a leaf kind of obj and push the element to 'finalArr' array
Else, then iterate across all the elements of 'finalArr' over a recursion function
public findNode(ele, obj){
if(ele.children.length === 0){
if(ele.name === obj.parentGroup){
let child = {name:obj.groupName, children:[]};
ele.children.push(child);
}
}else{
let j = ele.children.length-1;
this.findNode(ele.children[j--],obj);
}
}
This recursion function will check the element has children or not, if no children, then compare the parentGroup of given obj, with name of element from 'FinalArr'.
if so ,push the current obj to the children of the element of finalArr.
else, that is, when children has more elements, the same recursion will be triggered until depth of the element is reached.
With this i tought i would make a tree structure with given inputs array, but when a parent has more children, of same level, this logic fails,
so the inputs array has 'c1' which is a child of 'p1', but nly the child 'c2' resides, not sure the what is that i missed.
You could take a standard algorithm for getting a tree with given data
const
getTree = (data, id, parent, root, fn = o => o) => {
var t = {};
data.forEach(o => ((t[o[parent]] ??= {}).children ??= []).push(Object.assign(t[o[id]] = t[o[id]] || {}, fn(o))));
return t[root].children;
},
data = [{ id: "614344d9d9c21c0001e6af2e", groupName: "Unassigned", parentGroup: "null" }, { id: "614447da152f69c3c1d52f2e", groupName: "P1", parentGroup: "null" }, { id: "614447da152f69c3c1d52f38", groupName: "K1", parentGroup: "C1" }, { id: "614447da152f69c3c1d52f3e", groupName: "A2", parentGroup: "C2" }, { id: "614447da152f69c3c1d52f40", groupName: "G1", parentGroup: "P2" }, { id: "614447da152f69c3c1d52f46", groupName: "F1", parentGroup: "null" }, { id: "614447da152f69c3c1d52f30", groupName: "P2", parentGroup: "null" }, { id: "614447da152f69c3c1d52f36", groupName: "C2", parentGroup: "P1" }, { id: "614447da152f69c3c1d52f3c", groupName: "A1", parentGroup: "C2" }, { id: "614447da152f69c3c1d52f34", groupName: "C1", parentGroup: "P1" }, { id: "614447da152f69c3c1d52f32", groupName: "P3", parentGroup: "null" }, { id: "614447da152f69c3c1d52f3a", groupName: "K2", parentGroup: "C1" }, { id: "614447da152f69c3c1d52f42", groupName: "GG1", parentGroup: "G1" }, { id: "614447da152f69c3c1d52f44", groupName: "GGG1", parentGroup: "GG1" }],
tree = getTree(data, 'groupName', 'parentGroup', null, ({ groupName: name }) => ({ name }));
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think the issue is how finalArr is used to generate the html elements.
When doing console.log(finalArr) it looks like the code block below. So it seems to me like the code you have to build the structure of finalArr is working fine.
// console.log(finalArr)
[
{ "name": "P3", "children": [] },
{
"name": "P2",
"children": [
{
"name": "G1",
"children": [
{ "name": "GG1", "children": [
{ "name": "GGG1", "children": [] }
]
}
]
}
]
},
{ "name": "F1", "children": [] },
{
"name": "P1",
"children": [
{ "name": "C2", "children": [
{ "name": "A1", "children": [] }
]
}
]
},
{ "name": "Unassigned", "children": [] }
]
EDIT
As OP mentioned in the comment C1 was missing. I've introduced a root element that will have the finalArr as its children and changed the findNode to use a for loop instead of forEach. In this way we can also break when we find the node and not continue recursing.
As part of the initial sorting we will sort the inputs by parentGroup so we ensure that a childs parent is added in the tree structure before we try to find it with findNode.
I believe this produces the correct result:
inputs.sort((a, b) => (a.parentGroup === "null" ? -1 : 1));
// Sort by parentGroup
let root = inputs.pop();
let inputsDescending = [root];
let max = inputs.length * inputs.length;
let c = 0;
while (inputs.length > 0 && max > c) {
const child = inputs.pop();
const hasParentGroup = inputsDescending.find(
(parent) => parent.groupName === child.parentGroup
);
if (hasParentGroup || child.parentGroup === "null") {
inputsDescending.push(child);
} else {
inputs.unshift(child);
}
}
let rootEle = { name: "root", children: [] };
inputsDescending.forEach((obj) => {
if (obj.parentGroup === "null") {
let child = { name: obj.groupName, children: [] };
rootEle.children.push(child);
} else {
findNode(rootEle, obj);
}
});
function findNode(ele, obj) {
if (ele.name === obj.parentGroup) {
let child = { name: obj.groupName, children: [] };
ele.children.push(child);
return true;
} else {
const c = ele.children.length;
if (c > 0) {
for (let i = 0; c > i; i++) {
const found = findNode(ele.children[i], obj);
if (found) break;
}
}
}
}
const finalArr = rootEle.children;
Now finalArr looks like this:
[
{ "name": "Unassigned", "children": [] },
{
"name": "P1",
"children": [
{
"name": "C1",
"children": [
{ "name": "K1", "children": [] },
{ "name": "K2", "children": [] }
]
},
{
"name": "C2",
"children": [
{ "name": "A2", "children": [] },
{ "name": "A1", "children": [] }
]
}
]
},
{ "name": "F1", "children": [] },
{
"name": "P2",
"children": [
{ "name": "G1", "children": [
{ "name": "GG1", "children": [] }
]
}
]
},
{ "name": "P3", "children": [] }
]

Is there a way to execute .map recursively for every array in an array in JavaScript/TypeScript?

I currently have this array which repeats recursively:
[
{
"Name": "Test",
"Children": [
{
"Name": "Id",
"Property": "Placeholder",
"Children": [
{
"Name": "Child Id",
"Property": "Placeholder",
"Children": null
}
]
}
}
]
To get the structure I want I currently have this:
const fixed = data.map(item => item = {
data: {
name: item.Name,
},
children: item.Children.map(child => child = {
name: child.Name,
})
}
)
Is there a way to repeat my initial array.map recursively for each child array?
One possible solution, based on the output I believe you want:
const array = [{
"Name": "Test",
"Children": [{
"Name": "Id",
"Property": "Placeholder",
"Children": [{
"Name": "Child Id 1",
"Property": "Placeholder",
"Children": null
}, {
"Name": "Child Id 2",
"Property": "Placeholder",
"Children": [{
"Name": "Child Id 3",
"Property": "Placeholder",
"Children": null
}]
}]
}]
}];
const map = (arr) => {
return arr ? arr.map(fix) : null;
}
const fix = (item) => {
return {
data: {
name: item.Name
},
children: map(item.Children),
};
}
console.log(map(array))
Or as suggested below, use shortands:
const map = arr => arr ? arr.map(fix) : null;
const fix = item => ({
data: {
name: item.Name
},
children: map(item.Children),
});
We can use a base case where we check if the Children property is null,if so recursion stops and we return the Name:
const data = [{"Name": "Test", "Children": [{"Name": "Id","Property": "Placeholder","Children": [{"Name": "Child Id","Property": "Placeholder","Children": null }] }] }];
const flattenData = (data) => {
return data.map(d => {
//Base case, recursion stops here
if(!d.Children){
return d.Name;
}
//Continue recursion
return {data: {name: d.Name}, children: flattenData(d.Children) }
});
}
console.log(flattenData(data));
You can create a function that transforms children. If the child has other children, then the function will call itself to transform them recursively.
const input = [
{
"Name": "Test",
"Children": [
{
"Name": "Id",
"Property": "Placeholder",
"Children": [
{
"Name": "Child Id",
"Property": "Placeholder",
"Children": null
}
]
}
]
}
];
const transformChildren = children => children.map(child => ({
name: child.Name,
children: child.Children ? transformChildren(child.Children) : null
}));
const output = input.map(item => ({
data: {
name: item.Name,
},
children: item.Children ? transformChildren(item.Children) : null
}))
console.log(output)

Javascript - Updating ParentId to in nested objects

I currently store a structure in a javascript Array with nested objects. The structure does not have a parentId parameter which I do need to get the parent of a nested object. The current structure outputs:
[{
"id":1000,
"pageIndex":0,
"type":"page",
"label":"Page 1",
"rows":[
{
"id":1002,
"type":"row 1",
"layout":{
"gutters":true,
"wrapping":false,
"guttersDirect":false,
"parentId":1002
},
"columns":[
{
"id":1003,
"type":"col 1",
"layout":{
"size":3,
"outOf":12,
"parentId":1003
}
},
{
"id":1004,
"type":"col 2",
"layout":{
"size":3,
"outOf":12,
"parentId":1004
},
"elements":[
{
"id":1006,
"type":"text",
"label":"Account ID"
}
]
},
{
"id":1005,
"type":"col 3",
"layout":{
"size":6,
"outOf":12,
"parentId":1005
}
}
]
}
]
}]
I need a function that updates all nested objects' parentId attribute with the parent nested object's id.
I have the following function
_PREV_PARENT_ID = null;
assignParentIds(object){
Object.keys(object).forEach(key => {
console.log(`key: ${key}, value: ${object[key]}`)
if(key === "id"){
this._PREV_PARENT_ID = object[key];
}else if (typeof object[key] === 'object') {
if(!!this._PREV_PARENT_ID){
object[key]['parentId'] = this._PREV_PARENT_ID;
}
this.assignParentIds(object[key])
}
});
}
However, this function fails to set parent ids correctly for items in array
[
{
"id":1000,
"pageIndex":0,
"type":"page",
"label":"Page 1",
"rows":[
{
"id":1002,
"parentId":1000,
"type":"row 1",
"layout":{
"gutters":true,
"wrapping":false,
"guttersDirect":false,
"parentId":1002
},
"columns":[
{
"id":1003,
"parentId":1002, <--- Correct
"type":"col 1",
"layout":{
"size":3,
"outOf":12,
"parentId":1003
}
},
{
"id":1004,
"parentId":1003, <--- In-Correct
"type":"col 2",
"layout":{
"size":3,
"outOf":12,
"parentId":1004
},
"elements":[
{
"id":1006,
"parentId":1004,
"type":"text",
"label":"Account ID"
}
]
},
{
"id":1005,
"parentId":1006, <--- In-Correct
"type":"col 3",
"layout":{
"size":6,
"outOf":12,
"parentId":1005
}
}
]
}
]
}
]
I thought about also potentially ditching parentId attribute and instead to use a function that would return the parent nested, however it also suffers from the same issue (if I call the function on id = 1004, it returns the previous item in the array with id = 1003 instead of returning the object with id 1002.
_PARENT_OBJECT = null;
findParentByChildId(o, id) {
if( o.id === id ){
return o;
}else{
if(o.hasOwnProperty('id')){
this._PARENT_OBJECT = o;
}
}
var result, p;
for (p in o) {
if( o.hasOwnProperty(p) && typeof o[p] === 'object' ) {
result = this.findParentByChildId(o[p], id);
if(result){
return this._PARENT_OBJECT;
}
}
}
return result;
}
Since the use case is about using drag and drop functionality, the parentId will often be updated and seems like an uneccesary extra attribute that we need to keep track of, it would be best if I had a way to call a function findParentByChildId().
What would be the best way to manage this?
I wanted to take a chance to figure it out. I've made a walker function which goes through every level and array and brings the id of the previous level with it. Then when it gets a match on an id it returns the parent id you are looking for. Or when it has no match it returns null.
const data = [{
"id": 1000,
"pageIndex": 0,
"type": "page",
"label": "Page 1",
"rows": [{
"id": 1002,
"type": "row 1",
"layout": {
"gutters": true,
"wrapping": false,
"guttersDirect": false,
"parentId": 1002
},
"columns": [{
"id": 1003,
"type": "col 1",
"layout": {
"size": 3,
"outOf": 12,
"parentId": 1003
}
},
{
"id": 1004,
"type": "col 2",
"layout": {
"size": 3,
"outOf": 12,
"parentId": 1004
},
"elements": [{
"id": 1006,
"type": "text",
"label": "Account ID"
}]
},
{
"id": 1005,
"type": "col 3",
"layout": {
"size": 6,
"outOf": 12,
"parentId": 1005
}
}
]
}]
}];
const walkTree = (entry, matchId, parentId = null) => {
let result = null;
for (const { id, ...rest } of entry) {
if (matchId === id) {
return parentId;
}
parentId = id;
for (const value of Object.values(rest)) {
if (Array.isArray(value)) {
result = walkTree(value, matchId, parentId);
break;
}
}
}
return result;
};
const findParentByChildId = id => walkTree(data, id);
// ID's to look up parents of.
const lookupParents = [
1000,
1002,
1003,
1004,
1005,
1006,
1007
];
// Log results.
for (const id of lookupParents) {
console.log(`Parent of ${id}:`, findParentByChildId(id));
}

How to find the parent JSON object vaue using the child object value dynamically in Javascript?

var obj = [
{
"name": "A1",
"children": [
{
"name": "A1-level1-child1",
"children": [
{
"name": "A1-level2-child1",
"children": [
{
"name": "A1-level3-child1",
"children": []
},
{
"name": "A1-level3-child2",
"children": []
}
]
}
]
},
{
"name": "A2-level1-child1",
"children": []
}
]
},
{
"name": "B1",
"children": [
]
}
];
From the above JSON object, if i check the value "A1-level3-child1", the function should give me its parent name as "A1-level2-child1". Same way, if i check for "A2-level1-child1",then it should be give me the parent value as "A1".
You could iterate the array or children and use a short circuit if the node is found.
function getParentName(array, name, parent = 'root') {
var result;
array.some(o => result = o.name === name && parent
|| o.children && getParentName(o.children, name, o.name));
return result;
}
var array = [{ name: "A1", children: [{ name: "A1-level1-child1", children: [{ name: "A1-level2-child1", children: [{ name: "A1-level3-child1", children: [] }, { name: "A1-level3-child2", children: [] }] }] }, { name: "A2-level1-child1", children: [] }] }, { name: "B1", children: [] }];
console.log(getParentName(array, "A1-level3-child1")); // A1-level2-child1
console.log(getParentName(array, "A2-level1-child1")); // A1
GoGo this code.
var parentMap = {}
function getParentMap(arr, parent) {
if (!(arr instanceof Array)) {
return;
}
for (o of arr) {
parentMap[o.name] = parent;
if (o.children && o.children.length) {
getParentMap(o.children, o);
//getParentMap(o.children, o.name);
}
}
}
var arr = [{
"name": "A1",
"children": [{
"name": "A1-level1-child1",
"children": [{
"name": "A1-level2-child1",
"children": [{
"name": "A1-level3-child1",
"children": []
},
{
"name": "A1-level3-child2",
"children": []
}
]
}]
},
{
"name": "A2-level1-child1",
"children": []
}
]
},
{
"name": "B1",
"children": []
}];
getParentMap(obj, null);
parentMap["A1-level3-child1"].name
If you can redefine this structure, you can add 'parent' on every node, so more easy to operate it.

Construct flat array from tree of objects

Suppose I have a tree of objects like the following, perhaps created using the excellent algorithm found here: https://stackoverflow.com/a/22367819/3123195
{
"children": [{
"id": 1,
"title": "home",
"parent": null,
"children": []
}, {
"id": 2,
"title": "about",
"parent": null,
"children": [{
"id": 3,
"title": "team",
"parent": 2,
"children": []
}, {
"id": 4,
"title": "company",
"parent": 2,
"children": []
}]
}]
}
(Specifically in this example, the array returned by that function is nested as the children array property inside an otherwise empty object.)
How would I convert it back to a flat array?
Hope your are familiar with es6:
let flatten = (children, extractChildren) => Array.prototype.concat.apply(
children,
children.map(x => flatten(extractChildren(x) || [], extractChildren))
);
let extractChildren = x => x.children;
let flat = flatten(extractChildren(treeStructure), extractChildren)
.map(x => delete x.children && x);
UPD:
Sorry, haven't noticed that you need to set parent and level. Please find the new function below:
let flatten = (children, getChildren, level, parent) => Array.prototype.concat.apply(
children.map(x => ({ ...x, level: level || 1, parent: parent || null })),
children.map(x => flatten(getChildren(x) || [], getChildren, (level || 1) + 1, x.id))
);
https://jsbin.com/socono/edit?js,console
This function will do the job, plus it adds a level indicator to each object. Immediate children of treeObj will be level 1, their children will be level 2, etc. The parent properties are updated as well.
function flatten(treeObj, idAttr, parentAttr, childrenAttr, levelAttr) {
if (!idAttr) idAttr = 'id';
if (!parentAttr) parentAttr = 'parent';
if (!childrenAttr) childrenAttr = 'children';
if (!levelAttr) levelAttr = 'level';
function flattenChild(childObj, parentId, level) {
var array = [];
var childCopy = angular.extend({}, childObj);
childCopy[levelAttr] = level;
childCopy[parentAttr] = parentId;
delete childCopy[childrenAttr];
array.push(childCopy);
array = array.concat(processChildren(childObj, level));
return array;
};
function processChildren(obj, level) {
if (!level) level = 0;
var array = [];
obj[childrenAttr].forEach(function(childObj) {
array = array.concat(flattenChild(childObj, obj[idAttr], level+1));
});
return array;
};
var result = processChildren(treeObj);
return result;
};
This solution takes advantage of Angular's angular.extend() function to perform a copy of the child object. Wiring this up with any other library's equivalent method or a native function should be a trivial change.
The output given for the above example would be:
[{
"id": 1,
"title": "home",
"parent": null,
"level": 1
}, {
"id": 2,
"title": "about",
"parent": null,
"level": 1
}, {
"id": 3,
"title": "team",
"parent": 2,
"level": 2
}, {
"id": 4,
"title": "company",
"parent": 2,
"level": 2
}]
It is also worth noting that this function does not guarantee the array will be ordered by id; it will be based on the order in which the individual objects were encountered during the operation.
Fiddle!
Here it goes my contribution:
function flatNestedList(nestedList, childrenName, parentPropertyName, idName, newFlatList, parentId) {
if (newFlatList.length === 0)
newFlatList = [];
$.each(nestedList, function (i, item) {
item[parentPropertyName] = parentId;
newFlatList.push(item);
if (item[childrenName] && item[childrenName].length > 0) {
//each level
flatNestedList(item[childrenName], childrenName, parentPropertyName, idName, newFlatList, item[idName]);
}
});
for (var i in newFlatList)
delete (newFlatList[i][childrenName]);
}
Try following this only assumes each item is having children property
class TreeStructureHelper {
public toArray(nodes: any[], arr: any[]) {
if (!nodes) {
return [];
}
if (!arr) {
arr = [];
}
for (var i = 0; i < nodes.length; i++) {
arr.push(nodes[i]);
this.toArray(nodes[i].children, arr);
}
return arr;
}
}
Usage
let treeNode =
{
children: [{
id: 1,
title: "home",
parent: null,
children: []
}, {
id: 2,
title: "about",
parent: null,
children: [{
id: 3,
title: "team",
parent: 2,
children: []
}, {
id: 4,
title: "company",
parent: 2,
children: []
}]
}]
};
let flattenArray = _treeStructureHelper.toArray([treeNode], []);
This is data:
const data = {
id: '1',
children: [
{
id: '2',
children: [
{
id: '4',
children: [
{
id: '5'
},
{
id: '6'
}
]
},
{
id: '7'
}
]
},
{
id: '3',
children: [
{
id: '8'
},
{
id: '9'
}
]
}
]
}
In React.JS just declare an array field in state and push items to that array.
const getAllItemsPerChildren = item => {
array.push(item);
if (item.children) {
return item.children.map(i => getAllItemsPerChildren(i));
}
}
After function call your array in state will hold all items as below:
One more 😄😁
function flatten(root, parent=null, depth=0, key='id', flat=[], pick=() => {}) {
flat.push({
parent,
[key]: root[key],
depth: depth++,
...pick(root, parent, depth, key, flat)
});
if(Array.isArray(root.children)) {
root.children.forEach(child => flatten(child, root[key], depth, key, flat, pick));
}
}
let sample = {
"id": 0,
"children": [{
"id": 1,
"title": "home",
"parent": null,
"children": []
}, {
"id": 2,
"title": "about",
"parent": null,
"children": [{
"id": 3,
"title": "team",
"parent": 2,
"children": []
}, {
"id": 4,
"title": "company",
"parent": 2,
"children": []
}]
}]
};
let flat = [];
flatten(sample, null, 0, 'id', flat, root => ({ title: root.title }));
let expected = [
{
"id": 0,
"parent": null,
"depth": 0
},
{
"id": 1,
"parent": 0,
"depth": 1,
"title": "home"
},
{
"id": 2,
"parent": 0,
"depth": 1,
"title": "about"
},
{
"id": 3,
"parent": 2,
"depth": 2,
"title": "team"
},
{
"id": 4,
"parent": 2,
"depth": 2,
"title": "company"
}
];

Categories