从深层嵌套对象内的值获取父键和祖父母键

时间:2019-08-29 13:19:13

标签: javascript json object

我有一个深层嵌套的JavaScript对象,并且知道一个值位于该对象的最低位置。我想知道父键和祖父母键。

我设置了一个jsbin https://jsbin.com/yimugezuxe/edit?js,console

基于值“ uniqueID#9aserdf”,我想知道/返回其父键:下一个对象的“阶段2”和“级别2”:

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'

4 个答案:

答案 0 :(得分:2)

类似这样的东西:

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

  }
}

然后使用此方法向下迭代并检查

这是一个完整的例子:

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

您可以删除代码中的注释,以帮助查看您在对象中的位置。

答案 1 :(得分:2)

尝试以下代码:

它使用递归并提供父节点。

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 :(得分:1)

这是一个返回带有Level和Stage的元组的函数,如果没有匹配的ChildrenId,则返回[null,null]。

这有点混乱,但是我还没有找到一种简单的方法。

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

答案 3 :(得分:0)

我将this answergetObjectZach修改为Find by key deep in a nested object,以接受属性名称和值。

我将this answerfindPathibrahim mahrir直接拉到Javascript - Find path to object reference in nested object

将它们组合在一起,可以获取包含要查找的属性的对象,然后使用该对象获取该对象的路径。您可以更改findPath以返回字符串数组,如果需要的话,可以仅拉前两个字符串。

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