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

时间:2019-01-05 09:39:07

标签: javascript arrays json object

我想访问给定目标密钥的所有父项 例如,我想给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;
        }
    }
}

3 个答案:

答案 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)

  

Prune JSON to given target and get all parent keys

我发现此问题非常有趣,并尝试使用递归按如下方式解决(以模块化方式)。

  

这里只有 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();