I found this problem very interesting and tried to solve (in a modular way) using recursion as follows.
Here only getParentKeys() will return you the expected result as you want.
Other functions are just helpers(callees) or independent.
Just go through the code starting from function testcase() which is starter.
Corrected one (Improved version of 2nd one)
function getAllMatchedKeys(testData, searchWord) {
let type = Object.prototype.toString.call(testData).slice(8, -1) // Array, Object, String, Number
let arr = [];
if(type == 'Object') { // If it is object
let keys = Object.keys(testData);
for(let key of keys) {
if(key === searchWord) {
arr.push(key);
return arr;
}
if(Object.prototype.toString.call(testData[key]).slice(8, -1) === 'Object') {
arr = getAllMatchedKeys(testData[key], searchWord);
if(arr.length !== 0) {
arr.push(key)
return arr;
}
}
}
}
return arr;
}
function getKeys(testData, searchWord) {
let allKeys = getAllMatchedKeys(testData, searchWord);
let parentKeys = allKeys.slice(1).reverse();
let keys = {
allKeys: allKeys,
parentKeys: parentKeys
};
return keys;
}
function getParentKeys(testData, searchWord) {
/*
Returns the parent keys, excluing the search word
*/
let keys = getKeys(testData, searchWord);
return keys["parentKeys"];
}
function testcase() {
/*
Test cases
*/
let testData = {
cars: {
sedan: {
toyota: 'value1',
kia: 'value2',
mercedes: 'value3'
},
compact: {
bugatti: 'value1'
},
toyota: {
car1: 'car-1',
car2: 'car-2',
car3: {
redbull: 'favourite'
}
}
},
electronics: {
computers: {
mac: {
macbook_pro: "value 1 1",
macbook_air: "value 1 2"
},
pcs: 'value2'
},
mobiles: {
apple: "value",
samsung: "value"
}
}
};
// TEST CASE 1
let macbookAllKeys = getKeys(testData, 'macbook_pro'); // Object
/*
{ allKeys: [ 'macbook_pro', 'mac', 'computers', 'electronics' ],
parentKeys: [ 'electronics', 'computers', 'mac' ] }
*/
// Pretty printing
console.log(JSON.stringify(macbookAllKeys, null, 4));
/*
{
"allKeys": [
"macbook_pro",
"mac",
"computers",
"electronics"
],
"parentKeys": [
"electronics",
"computers",
"mac"
]
}
*/
let macbookParentKeys = getParentKeys(testData, 'macbook_pro');
console.log(macbookParentKeys); /* [ 'electronics', 'computers', 'mac' ] */
// TEST CASE 2
let kiaParentKeys = getParentKeys(testData, 'kia');
console.log(kiaParentKeys); /* [ 'cars', 'sedan' ] */
// TEST CASE 3 (I added extra keys to your testData for this)
let redbullParentKeys = getParentKeys(testData, 'redbull');
console.log(redbullParentKeys); /* [ 'cars', 'toyota', 'car3' ] */
// TEST CASE 4
let sedanParentKeys = getParentKeys(testData, 'sedan');
console.log(sedanParentKeys); /* [ 'cars' ] */
}
// Start
testcase();
Does not work if key points to object and user is looking for that key (Above one is correct)
function getAllMatchedKeys(testData, searchWord) {
let type = Object.prototype.toString.call(testData).slice(8, -1) // Array, Object, String, Number
let arr = [];
if(type == 'Object') { // If it is object
let keys = Object.keys(testData);
for(let key of keys) {
if(Object.prototype.toString.call(testData[key]).slice(8, -1) === 'Object') {
arr = getAllMatchedKeys(testData[key], searchWord);
if(arr.length !== 0) {
arr.push(key)
return arr;
}
} else {
if(key === searchWord) {
arr.push(key);
return arr;
}
}
}
}
return arr;
}
function getKeys(testData, searchWord) {
let allKeys = getAllMatchedKeys(testData, searchWord);
let parentKeys = allKeys.slice(1).reverse();
let keys = {
allKeys: allKeys,
parentKeys: parentKeys
};
return keys;
}
function getParentKeys(testData, searchWord) {
/*
Returns the parent keys, excluing the search word
*/
let keys = getKeys(testData, searchWord);
return keys["parentKeys"];
}
function testcase() {
/*
Test cases
*/
let testData = {
cars: {
sedan: {
toyota: 'value1',
kia: 'value2',
mercedes: 'value3'
},
compact: {
bugatti: 'value1'
},
toyota: {
car1: 'car-1',
car2: 'car-2',
car3: {
redbull: 'favourite'
}
}
},
electronics: {
computers: {
mac: {
macbook_pro: "value 1 1",
macbook_air: "value 1 2"
},
pcs: 'value2'
},
mobiles: {
apple: "value",
samsung: "value"
}
}
};
// TEST CASE 1
let macbookAllKeys = getKeys(testData, 'macbook_pro'); // Object
/*
{ allKeys: [ 'macbook_pro', 'mac', 'computers', 'electronics' ],
parentKeys: [ 'electronics', 'computers', 'mac' ] }
*/
// Pretty printing
console.log(JSON.stringify(macbookAllKeys, null, 4));
/*
{
"allKeys": [
"macbook_pro",
"mac",
"computers",
"electronics"
],
"parentKeys": [
"electronics",
"computers",
"mac"
]
}
*/
let macbookParentKeys = getParentKeys(testData, 'macbook_pro');
console.log(macbookParentKeys); /* [ 'electronics', 'computers', 'mac' ] */
// TEST CASE 2
let kiaParentKeys = getParentKeys(testData, 'kia');
console.log(kiaParentKeys); /* [ 'cars', 'sedan' ] */
// TEST CASE 3 (I added extra keys to your testData for this)
let redbullParentKeys = getParentKeys(testData, 'redbull');
console.log(redbullParentKeys); /* [ 'cars', 'toyota', 'car3' ] */
}
// Start
testcase();