问题
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