I have a deeply nested structure in the javascript object without any arrays in it.
var data = {
bar: 'a',
child: {
b: 'b',
grand: {
greatgrand: {
c: 'c'
}
}
}
};
let arr = [];
const findParentGrandparent = (obj, target) => {
Object.entries(obj).forEach(child => {
if (typeof child[1] === 'object') {
findParentGrandparent(child[1]);
}
});
};
findParentGrandparent(data, 'c');
When I call the function with a target, I want to get the taget key itself, parent and grandparent. For example, if the target is 'c', arr should become
['c', 'greatgrand', 'grand', 'child'];
if target is 'greatgrand', it should become
['greatgrand', 'grand', 'child'];
Thanks
You can use a recursive generator function:
function* get_vals(d, target, c = []){
for (var i of Object.keys(d)){
if (i === target){
yield [target, ...c.slice(0, 3)]
}
if (typeof d[i] === 'object'){
yield* get_vals(d[i], target, c = [i, ...c])
}
}
}
var result = get_vals(data, 'c').next().value
Output:
["c", "greatgrand", "grand", "child"]
var data = {
bar: 'a',
child: {
b: 'b',
grand: {
greatgrand: {
c: 'c'
}
}
}
};
/**
* @param validate {boolean} = true - Pass true if need to check for existance of `target`
*/
const findParentGrandparent = (obj, target, validate = true) => {
let result = [];
for (let [key, value] of Object.entries(obj)) {
if (key === target) {
result.push(key);
break;
}
if (value.toString() === '[object Object]') {
result.push(key);
result = result.concat(findParentGrandparent(value, target, false))
}
}
if (validate && !result.includes(target)) {
return 'Not found';
}
return result;
};
let resultC = findParentGrandparent(data, 'c').reverse();
let resultGreatgrand = findParentGrandparent(data, 'greatgrand').reverse();
console.log('Result for "c":', resultC);
console.log('Result for "greatgrand":', resultGreatgrand);
I did it using your recursive pattern, you can change the way it handle errors also, here I throw if there is no result.
var data = {
bar: 'a',
child: {
b: 'b',
grand: {
greatgrand: {
c: 'c'
}
}
}
};
let arr = [];
const findParentGrandparent = (obj, target) => {
for (const child of Object.entries(obj)) {
if (typeof child[1] === 'object' && child[0] !== target) {
const result = findParentGrandparent(child[1], target);
return [...result, child[0]];
} else if (child[0] === target) {
return [child[0]];
}
};
throw new Error("not found"); // If it goes there the object is not found, you can throw or return a specific flag, as you wish.
};
console.log(findParentGrandparent(data, 'c'));