I have a json where one parent array, and every object of parent array there is another child array pozzles.
So what I want to do is, there is one key-value(title) of parent item I want to add in every item of child array.
Check this json screen shot to understand clear.
Is there any direct method available in js to do this ?
Considering this is your data
const data = [{ id: 1, title: "some", pozzles: [{ id: "1A" }, { id: "1B" }] }, { id: 2, title: "some2", pozzles: [{ id: "2A" }, { id: "2B" }] }];
data.forEach(d => {
d.pozzles.forEach(p => { p.title = d.title })
});
I have a javascript object with nested objects like this:
Object {
Id: 1,
Descendants: [{
Object {
id:2
Descendants:[
{Object
{id:3
Descendants[]
}}]}]
Now I want to iterate through all of the descendant properties and print them.
What would be the cleanest way to do this?
Thanks a lot in advance!
You could try this:
const o = {
id: 1,
Descendants: [
{
id: 2,
Descendants: [
{
id: 3,
Descendants: [],
},
],
},
],
}
function doSomething(o) {
// Write Do whatever you want to do with the objects
console.log(o.id)
// And to the recursively
for (const child of o.Descendants) {
doSomething(child)
}
}
doSomething(o)
I have a nested array. Like below:
I want to find the depth of this nested array, which means the child element has most deep nested children.
let arr = [
{
name: 'tiger',
children: [{
name: 'sinba',
children: [{
name: 'cute',
children: []
}]
}]
},
{
name: 'lion',
children: []
}
]
In this case, the depth is 3, the tiger has 3 level. So the depth is 3
How could i achieve this? I try to use recursive, but don't know how to find the element which
has most nested children.
Thanks in advance.
Assuming that there are no circular references, you could try something like this
let arr = [{
name: 'tiger',
children: [{
name: 'sinba',
children: [{
name: 'cute',
children: []
}]
}]
},
{
name: 'lion',
children: []
}
]
function count(children) {
return children.reduce((depth, child) => {
return Math.max(depth, 1 + count(child.children)); // increment depth of children by 1, and compare it with accumulated depth of other children within the same element
}, 0); //default value 0 that's returned if there are no children
}
console.log(count(arr))
Our function would not work if there were some circular references, so there might be a need to adjust it accordingly. Detecting circular references is a whole ordeal. If nothing is done about it, the function will throw a Maximum call stack size exceeded error.
In order to handle it without any additional functionality implementation you could use already existing native JSON.stringify to do so. The stringify option will throw an exception only if you try to serialize BigInt values which we can handle ourselves or when objects are cyclic, which is excatly what we wanted.
let arr = [{
name: 'tiger',
children: []
}]
function testCircular(arr){
try {
BigInt.prototype.toJSON = function() { return this.toString() } // Instead of throwing, JSON.stringify of BigInt now produces a string
JSON.stringify(arr);
return false;
}
catch (e) {
// will only enter here in case of circular references
return true;
}
}
function count(children) {
if (testCircular(children)) return Infinity;
return children.reduce((depth, child) => {
return Math.max(depth, 1 + count(child.children)); // increment depth of children by 1, and compare it with accumulated depth of other children within the same element
}, 0); //default value 0 that's returned if there are no children
}
console.log(count(arr)) // normally counting
arr[0].children = arr; // creates circular reference
console.log(count(arr)) // counting for circular
The parent id represents another category id which is its parent. With the dataset below I try to accomplish programmatically a structure like this:
| Cat Top Level 1
| Cat Top Level 2
| Cat Top Level 3
| --- Cat Top 3 Child 1
| --- Cat Top 3 Child 2
| ------ Cat Top 3 Child 2 Child 1
| --------- Cat Top 3 Child 2 Child 1 Child 1
| --- Cat Top 3 Child 3
The objects need to be merged into one and other. If a 'child' category is pushed into its direct 'parent' category it must come in a newly to create property called 'children' (array).
Dataset:
const categories = [
{
id: 16,
name: "Cat Top Level 1",
parent: 0,
},
{
id: 17,
name: "Cat Top Level 2",
parent: 0,
},
{
id: 18,
name: "Cat Top Level 3",
parent: 0,
},
{
id: 19,
name: "Cat Top 3 Child 1",
parent: 18,
},
{
id: 20,
name: "Cat Top 3 Child 2",
parent: 18,
},
{
id: 22,
name: "Cat Top 3 Child 2 Child 1",
parent: 20,
},
{
id: 23,
name: "Cat Top 3 Child 2 Child 1 Child 1",
parent: 22,
},
{
id: 21,
name: "Cat Top 3 Child 3",
parent: 18,
},
{
id: 15,
name: "Uncategorized",
parent: 0,
},
];
The code that I came up with so far goes like this.
function mergeCategories(categories) {
categories.map((category) => {
category.children = [];
if (category.parent === 0) {
return;
}
categories.map((subCategory) => {
if (subCategory.id !== category.parent) {
return;
}
});
});
}
Loop in a loop will return many duplicates. A .filter() seems to be needed as well, I guess. Due to performance .forEach() is excluded.
It is by far not complete, and does not work, of course. My mind is going crazy when I'm thinking of how to approach this. I thought It would be simple. But it's quite hard to be honest.
You could do this using recursive approach with reduce method that will check if the pid parameter is equal to id of the current element and if so add that object to the accumulator value. Then you also create recursive call to get children and if there is children found you add them as children property to current object. This will also expect that your root objects have parent value of 0.
const data = [{"id":16,"name":"Cat Top Level 1","parent":0},{"id":17,"name":"Cat Top Level 2","parent":0},{"id":18,"name":"Cat Top Level 3","parent":0},{"id":19,"name":"Cat Top 3 Child 1","parent":18},{"id":20,"name":"Cat Top 3 Child 2","parent":18},{"id":22,"name":"Cat Top 3 Child 2 Child 1","parent":20},{"id":23,"name":"Cat Top 3 Child 2 Child 1 Child 1","parent":22},{"id":21,"name":"Cat Top 3 Child 3","parent":18},{"id":15,"name":"Uncategorized","parent":0}]
function toNested(data, pid = 0) {
return data.reduce((r, e) => {
if (pid == e.parent) {
const object = { ...e }
const children = toNested(data, e.id);
if (children.length) {
object.children = children
}
r.push(object)
}
return r;
}, [])
}
const result = toNested(data);
console.log(result)
Have an addChild method, which will find the parent (recursively) and appends to children.
const tree = { id: 0, name: "root", children: [] };
const addChild = (obj, parent) => {
if (obj.parent === parent.id) {
parent.children.push({...obj, children: []});
} else {
parent.children.forEach((item) => addChild(obj, item));
}
};
const buildTree = (arr) => arr.forEach(obj => addChild(obj, tree));
const categories = [{"id":16,"name":"Cat Top Level 1","parent":0},{"id":17,"name":"Cat Top Level 2","parent":0},{"id":18,"name":"Cat Top Level 3","parent":0},{"id":19,"name":"Cat Top 3 Child 1","parent":18},{"id":20,"name":"Cat Top 3 Child 2","parent":18},{"id":22,"name":"Cat Top 3 Child 2 Child 1","parent":20},{"id":23,"name":"Cat Top 3 Child 2 Child 1 Child 1","parent":22},{"id":21,"name":"Cat Top 3 Child 3","parent":18},{"id":15,"name":"Uncategorized","parent":0}]
buildTree(categories);
console.log(tree);
I have a json object which has parent and child nodes. I would like to use an higher order function which can take all the parent and child nodes from n level. Which higher order function can be taken to display the details as :
Output:
Parent1
Parent2
Child1
SubChild1
SubChild2
Child2
Parent3
Child1
SubChild1
SubChild2
Json Object:
[{children:[], id:35, map_data:{தாலூகா:"மானாமதுரை"}, name:"Matae1"},
{children:[], id:36, map_data:{தாலூகா:"மானாமதுரை"}, name:"Matae2"},
{children:[{children:[], id:39, map_data:{தாலூகா:"மானாமதுரை"}, name:"Child1"}], id:36, map_data:{தாலூகா:"மானாமதுரை"}, name:"Matae3"}]
Structure is like:
When you need to traverse an arbitrarily you can use a simple recursive strategy: get the thing you want from the first level, like name and then pass the children to the same function. You can pass an array and level in with the function for convenience to keep track of the items and which level you are in at the moment.
For example (I've simplified your object to make it clearer):
let obj = [{
children: [],
name: "parent 1"
},
{
children: [{
children: [{
children: [],
name: "grandchild 1"
}, ],
name: "child 1"
},
{
children: [],
name: "child 2"
},
],
name: "parent 2"
},
{
children: [],
name: "parent 3"
},
]
function getChildren(arr, output = [], level = 0) {
arr.forEach(item => {
output.push(" ".repeat(level * 2) + item.name)
getChildren(item.children, output, level + 1)
})
return output
}
let out = getChildren(obj)
console.log(out.join('\n'))