简体   繁体   中英

How to create a JavaScript function to lookup objects and arrays nested within each other

I have an object with nested arrays and object that looks like this:

 // Recursive nested objects & arrays: var obj = { children: [{ parentname: "level 0, Benny", children: [{ parentname: "level 0.0, Stevey", children: [{ parentname: "level 0.0.0, Betty", children: [] }, { parentname: "level 0.0.1, AFGNCAAP", children: [{ parentname: "level 0.0.1.0, Moonman", children: [] }] } ] }, { parentname: "level 0.1, Oreo", children: [] } ] }, { parentname: "level 1, Jupiter", children: [] } ] }; // I am able to retrieve values with various length formulas: console.log(obj.children[0].parentname); // level 0, Benny console.log(obj.children[0].children[0].parentname); // level 0.0, Stevey console.log(obj.children[0].children[0].children[0].parentname); // level 0.0.0, Betty console.log(obj.children[0].children[0].children[1].parentname); // level 0.0.1, AFGNCAAP console.log(obj.children[0].children[0].children[1].children[0].parentname); // level 0.0.1.0, Moonman console.log(obj.children[0].children[1].parentname); // level 0.1, Oreo console.log(obj.children[1].parentname); // level 1, Jupiter // And I able to reduce formulas into functions...per level of nesting, example 1 level: function getNameWorking1(name, level) { console.log(obj[name][level].parentname); } getNameWorking1(["children"], [1]) // level 1, Jupiter // And example 2 levels: function getNameWorking2(name, level) { console.log(obj[name][level[0]][name][level[1]].parentname); } getNameWorking2(["children"], [ [0], [1] ]) // level 0.1, Oreo // I am trying to create a single function that I can send a parameter with the sequence of property name & array values. This does not work: function getNameNotWorking(parameter) { console.log(obj[parameter].parentname); } getNameNotWorking("[children][1]"); getNameNotWorking("[children][0][children][1]"); 

I am trying to create a single function that I can send a parameter with the sequence of property name & array values. This last function is not working. Any help on how to do this?

BTW. I have a recursive function that does work for this. But it works by every time starting at the beginning and look reading through each nested object & array until the item I am looking for is found. This seems it may be excessive to do repetitively. So I am looking for a method to look up the object once I already know it location - via all the children array values.

I feel you should pass your parameters separated by white sapace instead of swrapping in square brackets to make parsing and solution easier .

And. here you go :)

 function getNameWorking1(parameter, obj) { paramsList = parameter.split(' ').filter(prop => Boolean(prop)).map(prop => prop.trim()); return paramsList.reduce((val, prop) => { return val[prop]; }, obj).parentname; } //Working example: var obj = { children: [{ parentname: "level 0, Benny", children: [{ parentname: "level 0.0, Stevey", children: [{ parentname: "level 0.0.0, Betty", children: [] }, { parentname: "level 0.0.1, AFGNCAAP", children: [{ parentname: "level 0.0.1.0, Moonman", children: [] }] } ] }, { parentname: "level 0.1, Oreo", children: [] } ] }, { parentname: "level 1, Jupiter", children: [] } ] }; console.log(getNameWorking1("children 1", obj)); console.log(getNameWorking1("children 0 children 1", obj)); 

Your function doesn't work because it's taking the full string "[children][1]" and adding it in place of parameter , ie it's looking up obj["[children][1]"].parentname , which is undefined.

You need to input each key as parameters individually. Since you can't know how many parameters need to be passed, you need to iterate through the global arguments object.

Therefore, your function would look something like this:

function getNameNotWorking() {
  var returnValue = obj;
  for (let i = 0; i < arguments.length; i++) {
    returnValue = returnValue[arguments[i]];
  }
    console.log(returnValue);
}

Click here for working Codepen example.

You could do something like this using regex and reduce

 const obj = {children:[{parentname:"level 0, Benny",children:[{parentname:"level 0.0, Stevey",children:[{parentname:"level 0.0.0, Betty",children:[]},{parentname:"level 0.0.1, AFGNCAAP",children:[{parentname:"level 0.0.1.0, Moonman",children:[]}]}]},{parentname:"level 0.1, Oreo",children:[]}]},{parentname:"level 1, Jupiter",children:[]}]} const getNested = (object, str) => { let matches = [], match, regex = /\\[(.*?)\\]/g; while (match = regex.exec(str)) { matches.push(match[1]); } return matches.reduce((acc, key) => (acc || {})[key], object) } const nested = getNested(obj, "[children][0][children][1]") console.log(nested) 

  • Use /\\[(.*?)\\]/g to get the key names in a capturing group ( Regex101 )
  • Use exec to get all the key names from the capturing group to an array

     // matches ["children", "0", "children", "1" ] 
  • Use reduce to recursively get the nested property from the object

Check out JsonPath . It provides a clean interface around selecting JSON attributes without objects and there are plenty of JavaScript SDKs for it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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