Home > front end >  Iterate through nested object and return child keys as separate array
Iterate through nested object and return child keys as separate array

Time:11-02

I want to iterate through nested Object and I want to store the all the child keys as separate array and return it as a Object(parent key as key and child keys as value).

let a = {
  b: {
     f: {
       g: "hi",
       i: "wow"
      },
      e: "hello"
   },
c: {
   j: "ola"
  },
d: {
   k: ["bonjour","salam"]
  }
}

And I am expecting object like this.

{
  a:[b,c,d],
  b:[f,e],
  f:[g,i],
  c:[j],
  d:[k]
}

I tried and got result to some extent.

let res = {};
let keyVal;

var isObject1: any = val => {
if (typeof val === 'object' && val)
res[keyVal] = Object.keys(val);
}
function retrieveObj(obj1) {
for (const key in obj1) {
  const value1: any = obj1[key];
  keyVal = key;
  if (isObject1(value1))      
  retrieveObj(value1)
 }
}
res['a'] = Object.keys(a);
retrieveObj(a);

Below is the output which I got.

 {
  a: [ 'b', 'c', 'd' ], 
  b: [ 'f', 'e' ], 
  c: [ 'j' ], 
  d: [ 'k' ] 
 }

can any one help me to get complete output. Thanks in advance

CodePudding user response:

You have a few problems with your code

  1. your isObject1 check on whether something is an object or not, is not working correctly, because typeof [1,2,3] == 'object' will return true. You need an additional check for !Array.isArray(val)

  2. You are handling only the first level. You need a recursive call for nested objects.

  3. Not sure what compare is in your context

  4. You should not define keyval as a global variable. If you need to pass values from one scope to another, use parameters, not global variables.

The following should work

let a = {
  b: {
     f: {
       g: "hi",
       i: "wow"
      },
      e: "hello"
   },
c: {
   j: "ola"
  },
d: {
   k: ["bonjour","salam"]
  }
}

function getAllKeys(p, o, m) {
  if (!o || typeof o !== "object" || Array.isArray(o))
    return m;
  m[p] = Object.keys(o);
  
  for (let k of m[p])
    getAllKeys(k, o[k], m)

  return m;
}

let m = getAllKeys("a", a, {})
console.log(m)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

How does it work

The function getAllKeys accepts as parameters

  • p the name of the property to look at
  • o the value of the property to look at
  • m the result object where all the arrays are merged into

First, if the o which is passed in, is not a "real" object we just return because we don't need to do anything on arrays or primitive types. As typeof [...] and typeof null also return 'object' we need the two additional checks ...

Next we add all keys of the current object o to the result object under a key of p (ie the name of the object we are currently looking at)

And then we check all keys of o recursively. Ie, we pass the key k and value o[k] togehter with the result object m recursively into getAllKeys.

The final return m is just for convinience, so that we don't need to define the resultobject prior to the first call of getAllKeys. Without this return m we would need to call this as follows

let m = {};
getAllKeys("a", a, m); 

I don't know what you would expect from an object like the following

let a = {
  b: {
    c: {
      d: 3
    }
  },
  e: {
    c: {
      f: 4
    }
  }
}

The current approach will only return c: ['f']. If you want c: ['d', 'f'], you would need the following

m[p] = [ ...(m[p] || []), ...Object.keys(o)];
  • Related