Get parent and grandparent keys from a value inside a deep nested object [closed]

给你一囗甜甜゛ 提交于 2021-02-08 12:05:37

问题


I’ve got a deep nested JavaScript Object and I know a value which is at the object’s lowest position. I want to know the parent key and grandparent key.

I set up a jsbin https://jsbin.com/yimugezuxe/edit?js,console

Based on the value 'uniqueID#9aserdf' I want to know/return its parent keys: 'Stage 2' and 'Level 2' from the object below:

const obj = {
    "Level 1": {
        "Stage 1": [
        {
            "title": "Parent 1",
            "id": "Parent1#id",
            "Children": [
            {
                "title": "Steve",
                "id": "uniqueID1"
            },
            {
                "title": "James",
                "id": "uniqueID#9"
            }
            ]
        }
        ]
    },
    "Level 2": {
        "Stage 1": [
        {
            "title": "Parent 4",
            "id": "Parent4#id",
            "Children": [
            {
                "title": "Tim",
                "id": "uniqueIDadsf"
            },
            {
                "title": "Hans",
                "id": "uniqueID#9asdf"
            }
            ]
        }
        ],
        "Stage 2": [
        {
            "title": "Parent 10",
            "id": "Parent10#id",
            "Children": [
            {
                "title": "Chris",
                "id": "uniqueIDadsf33"
            },
            {
                "title": "Jack",
                "id": "uniqueID#9aserdf"
            }
            ]
        }
        ]
    }
};

// based on the value 'uniqueID#9aserdf' I want to know/return its parent keys: 'Stage 2' and 'Level 2'

回答1:


Try this code:

It uses recursion and will provide the parent nodes.

const obj = {
    "Level 1": {
        "Stage 1": [{
            "title": "Parent 1",
            "id": "Parent1#id",
            "Children": [{
                    "title": "Steve",
                    "id": "uniqueID1"
                },
                {
                    "title": "James",
                    "id": "uniqueID#9"
                }
            ]
        }]
    },
    "Level 2": {
        "Stage 1": [{
            "title": "Parent 4",
            "id": "Parent4#id",
            "Children": [{
                    "title": "Tim",
                    "id": "uniqueIDadsf"
                },
                {
                    "title": "Hans",
                    "id": "uniqueID#9asdf"
                }
            ]
        }],
        "Stage 2": [{
            "title": "Parent 10",
            "id": "Parent10#id",
            "Children": [{
                    "title": "Chris",
                    "id": "uniqueIDadsf33"
                },
                {
                    "title": "Jack",
                    "id": "uniqueID#9aserdf"
                }
            ]
        }]
    }
};

let path = [];


function getParentAndGrandParent(path, json, value) {

    for (var key in json) {

        if (typeof json[key] === 'object') {
            path.push(key.toString());
            // console.log("PAth : " + path)
            getParentAndGrandParent(path, json[key], value);
            path.pop();
        } else {
            if (json[key] == value) {
                console.log("Parent : " + path);
            }
        }
    }

}

getParentAndGrandParent(path, obj, 'uniqueID#9asdf')



回答2:


Something like this:

for (var prop in obj) {
  for (var prop2 in obj[prop]) {

  }
}

Then use this method to iterate down and check

Here is a full example:

for (var prop in obj) {
  for (var prop2 in obj[prop]) {
    //console.log(prop2);
    for (var prop3 in obj[prop][prop2]) {
      //console.log("->"+prop3);
      for (var prop4 in obj[prop][prop2][prop3]) {
        //console.log("->"+"->"+prop4);
        for (var prop5 in obj[prop][prop2][prop3][prop4]) {
          //console.log("->"+"->"+"->"+prop5);
          for (var prop6 in obj[prop][prop2][prop3][prop4][prop5]) {
            //console.log("->"+"->"+"->"+"->"+prop6);
            if (obj[prop][prop2][prop3][prop4][prop5][prop6] == "uniqueID#9aserdf") {
              console.log("Stage :" +prop2 + " == Level :" + prop);
            }
          }
        }
      }
    }
  }
}

you can take away the comments in the code, to help see where you are in the object.




回答3:


Here it is a function that returns a tuple with the Level and the Stage and if there is no matching ChildrenId returns [null, null].

It is a bit messy but I haven't found an easy way to do it.

const findAncestors = (obj, ChildrenId) => {

    let stageResult = null;

    const result = Object.entries(obj).find(level => {
        const validLevel = Object.values(level[1]).find((stage, index) => {
            const validId = stage[0].Children.some(children => {
                return children.id === ChildrenId
            })
            if (validId) {
                stageResult = Object.keys(level[1])[index];
            }
            return validId;
        })
        return validLevel != undefined;
    })

    return stageResult === null ? [null, null] : [result[0], stageResult];
}



回答4:


I modified getObject from this answer by Zach to Find by key deep in a nested object to accept a property name and value.

I pulled findPath directly from this answer by ibrahim mahrir to Javascript - Find path to object reference in nested object.

Combining them, you can get the object which contains the property your are looking for, then use that to get the path to that object. You can alter findPath to return an array of strings and pull just the first two if that's all you want.

function getObject(theObject, propName, propValue) {
    var result = null;
    if(theObject instanceof Array) {
        for(var i = 0; i < theObject.length; i++) {
            result = getObject(theObject[i], propName, propValue);
            if (result) {
                break;
            }   
        }
    }
    else
    {
        for(var prop in theObject) {
            //console.log(prop + ': ' + theObject[prop]);
            if(prop == propName) {
                if(theObject[prop] == propValue) {
                    return theObject;
                }
            }
            if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
                result = getObject(theObject[prop], propName, propValue);
                if (result) {
                    break;
                }
            } 
        }
    }
    return result;
}

function findPath(a, obj) {
    for(var key in obj) {                                         // for each key in the object obj
        if(obj.hasOwnProperty(key)) {                             // if it's an owned key
            if(a === obj[key]) return key;                        // if the item beign searched is at this key then return this key as the path
            else if(obj[key] && typeof obj[key] === "object") {   // otherwise if the item at this key is also an object
                var path = findPath(a, obj[key]);                 // search for the item a in that object
                if(path) return key + "." + path;                 // if found then the path is this key followed by the result of the search
            }
        }
    }
}

const data = {
    "Level 1": {
        "Stage 1": [
        {
            "title": "Parent 1",
            "id": "Parent1#id",
            "Children": [
            {
                "title": "Steve",
                "id": "uniqueID1"
            },
            {
                "title": "James",
                "id": "uniqueID#9"
            }
            ]
        }
        ]
    },
    "Level 2": {
        "Stage 1": [
        {
            "title": "Parent 4",
            "id": "Parent4#id",
            "Children": [
            {
                "title": "Tim",
                "id": "uniqueIDadsf"
            },
            {
                "title": "Hans",
                "id": "uniqueID#9asdf"
            }
            ]
        }
        ],
        "Stage 2": [
        {
            "title": "Parent 10",
            "id": "Parent10#id",
            "Children": [
            {
                "title": "Chris",
                "id": "uniqueIDadsf33"
            },
            {
                "title": "Jack",
                "id": "uniqueID#9aserdf"
            }
            ]
        }
        ]
    }
};
const o = getObject(data, "id", "uniqueID#9aserdf");
console.log(o);
const path = findPath(o, data);
console.log(path);


来源:https://stackoverflow.com/questions/57711141/get-parent-and-grandparent-keys-from-a-value-inside-a-deep-nested-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!