我想访问给定目标密钥的所有父项
例如,我想给macbook_pro
并得到这样的东西:
['electronics', 'computers', 'mac']
let testData = {
cars : {
sedan : {
toyota : 'value1',
kia : 'value2',
mercedes : 'value3'
},
compact : {
bugatti : 'value1',
bugatti : 'value1',
}
},
electronics : {
computers : {
mac : {
macbook_pro : "value 1 1",
macbook_air : "value 1 1"
},
pcs : 'value2'
},
mobiles : {
apple : 'value',
samsung : 'value'
}
}
};
我试图编写一个递归函数以获取所有键。它可以工作,但它也返回其他节点的所有键。
let keys = [];
function collectKeys(obj, breakKey){
for (let key in obj){
if (typeof obj[key] === 'object' && obj[key].constructor === Object){
keys.push(key);
collectKeys(obj[key], breakKey);
}
if (key === breakKey){
break;
}
}
}
答案 0 :(得分:3)
您可以使用此递归函数:
function getPath(obj, key) {
if (Object(obj) !== obj) return; // It's a primitive value: No match
if (key in obj) return []; // found it!
for (let prop in obj) {
const path = getPath(obj[prop], key);
if (path) return [prop, ...path];
}
}
const testData = {cars: {sedan: {toyota: 'value1',kia: 'value2',mercedes: 'value3'},compact: {bugatti: 'value1'}},electronics: {computers: {mac: {macbook_pro: 'value 1 1',macbook_air: 'value 1 1'},pcs: 'value2'},mobiles: {apple: 'value',samsung: 'value'}}};
console.log(getPath(testData, "pcs"));
您的代码中的问题是您不确定当前路径是否会导致匹配时执行keys.push(key);
。如果递归调用未找到匹配项,则应再次从keys
中弹出该键。
由于您的函数未返回任何内容,因此您真的不知道递归调用是否找到了匹配项,但这正是您所需要的。
答案 1 :(得分:1)
我使用递归树遍历算法找到了一条路径。
const testData = {
cars: {
sedan: {
toyota: 'value1',
kia: 'value2',
mersedes: 'value3'
},
compact: {
bugatti: 'value4'
}
},
electronics: {
computers: {
mac: {
macbook_pro: 'value5',
macbook_air: 'value6'
},
pcs: 'value7'
},
mobiles: {
apple: 'value8',
samsung: 'value9'
}
}
};
function getPath(dataObject, value) {
let foundPath;
function collectKeys(data, path = []) {
Object.keys(data).forEach(key => {
if (key === value) {
foundPath = path;
return;
}
if (typeof data[key] !== 'string') {
collectKeys(data[key], path.concat([key]));
}
});
}
collectKeys(dataObject);
return foundPath;
}
console.log((getPath(testData, 'sedan')).join(',') === ['cars'].join(','));
console.log((getPath(testData, 'macbook_pro')).join(',') === ['electronics', 'computers', 'mac'].join(','));
答案 2 :(得分:0)
我发现此问题非常有趣,并尝试使用递归按如下方式解决(以模块化方式)。
这里只有 getParentKeys()会根据您的期望返回结果。
其他功能仅仅是助手(被调用者)或独立的功能。
只需检查从启动器功能 testcase()开始的代码。
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();