简体   繁体   English

将JSON修剪到给定目标并获取所有父键

[英]Prune JSON to given target and get all parent keys

I want to access all parents of a given target key for example I want to give macbook_pro and get somthing like this : ['electronics', 'computers', 'mac'] 我想访问给定目标键的所有父级,例如,我想给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'
            }
        }

    };

I tried to write a recursive function to get all keys. 我试图编写一个递归函数以获取所有键。 It works but it return all keys of other nodes too. 它可以工作,但它也返回其他节点的所有键。

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;
        }
    }
}

You could use this recursive function: 您可以使用以下递归函数:

 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")); 

The problem in your code is that you do keys.push(key); 您的代码中的问题是您执行keys.push(key); at a time when it is not sure that the current path will lead to match. 在不确定当前路径是否会导致匹配时。 If the recursive call doesn't find a match then that key should be popped again from keys . 如果递归调用没有找到匹配项,那么该键应该从keys再次弹出。

As your function does not return anything, you really don't know whether the recursive call found a match or not, yet that is something you need. 由于函数不返回任何内容,因此您实际上不知道递归调用是否找到匹配项,但这是您所需要的。

I found a path using recursive tree traversal algorithm. 我发现了使用递归树遍历算法的路径。

 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(',')); 

Prune JSON to given target and get all parent keys 将JSON修剪到给定目标并获取所有父键

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. 在这里,只有getParentKeys()会根据需要返回您期望的结果。

Other functions are just helpers(callees) or independent. 其他功能只是助手(被调用者)或独立的。

Just go through the code starting from function testcase() which is starter. 只需通过从启动程序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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM