Home > OS >  How to get object path in nested array of objects?
How to get object path in nested array of objects?

Time:11-25

Im trying to get the full path of an array of objects by using recursion to loop over the array objects and get their path with relation to the parent, what i couldn't do was the part when the path reset and starts to add the "child" key .

      const data = {
        data: [
          {
            key: 'userInfo',
            group: [
              {
                key: 'street',
              },
              {
                key: 'phone',
              },
            ],
          },
          {
            key: 'fullName',
            group: [
              {
                key: 'firstName',
              },
              {
                key: 'lastName',
              },
            ],
          },
        ],
      };
// userInfo.street
// userInfo.phone
// fullName.firstName
// fullName.lastName
    let groupPath = '';
    data.data.forEach(function iter(a) {
      if (a.group) {
        groupPath = a.key;
      } else {
        groupPath = [groupPath, a.key].join('.');
      }
      Array.isArray(a.group) && a.group.forEach(iter);
      console.log(' group', groupPath);
    });
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

The finale result should look like this :

userInfo.street

userInfo.phone

fullName.firstName

fullName.lastName

CodePudding user response:

It seems like you can maintain an array of all the groups and just do a couple loops to get this done. The following should do it for you

const data={data:[{key:"userInfo",group:[{key:"street"},{key:"phone"}]},{key:"fullName",group:[{key:"firstName"},{key:"lastName"}]}]};

const groups = [];

data.data.forEach(el => {
  if (el.group) {
    el.group.forEach(group => {
       groups.push(`${el.key}.${group.key}`);
    })
  }
})

console.log(groups);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Updated logic.

Issue with current code

You are over writing groupPath with the child node details inside the else block of your execution.

const data={data:[{key:"userInfo",group:[{key:"street"},{key:"phone"}]},{key:"fullName",group:[{key:"firstName"},{key:"lastName"}]}]};
let groupPath = '';
let rootGroupPath = '';
let groupList = [];
data.data.forEach(function iter(a) {
  if (a.group) {
    rootGroupPath = a.key;
  } else {
    groupPath = [rootGroupPath, a.key].join('.');
    groupList.push(groupPath);
  }
  Array.isArray(a.group) && a.group.forEach(iter);
});
console.log(' group', groupList);
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Simplified approach

Use Array.flatMap

Logic

  • Loop through data.data array.
  • Inside each data node in this Array, run a Array.map and return key from outer node and key from group node.

Working Fiddle

const data = { data: [{ key: "userInfo", group: [{ key: "street" }, { key: "phone" }] }, { key: "fullName", group: [{ key: "firstName" }, { key: "lastName" }] }] };
const groupList = data.data.flatMap((data) => data.group.map((group) => `${data.key}.${group.key}`));
console.log(' group', groupList);
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Here is a recursion function that can get the paths with unlimited layer.

const data = {
        data: [
          {
            key: 'userInfo',
            group: [
              {
                key: 'street',
                group:[
                  { 
                    key: 'city',
                    group: [
                      {key: 'country'}
                    ]
                  }
                ]
              },
              {
                key: 'phone',
              },
            ],
          },
          {
            key: 'fullName',
            group: [
              {
                key: 'firstName',
              },
              {
                key: 'lastName',
              },
            ],
          },
        ],
      };
      
function getPaths({key,group})
{
  return Array.isArray(group) ? group.flatMap(it => getPaths(it).map(path => key != null ? `${key}.${path}` : path)) : [key];
}

const paths = getPaths({key:null,group:data.data});
console.log(paths);
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can use a forEach method for this, instead of using a recursion.

Show code snippet

const data = {
  data: [{
      key: 'userInfo',
      group: [{
          key: 'street',
        },
        {
          key: 'phone',
        },
      ],
    },
    {
      key: 'fullName',
      group: [{
          key: 'firstName',
        },
        {
          key: 'lastName',
        },
      ],
    },
  ],
};

let res = [];
data.data.forEach((i)=>{
   let key = i.key;
   i.group.forEach((j)=>{
    let str = key   "."   j.key;
    res.push(str);
   });
})

console.log(res);

// userInfo.street
// userInfo.phone
// fullName.firstName
// fullName.lastName
<iframe name="sif6" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>


If you need to use recursion, you can check this snippet out.

const data = {
  data: [{
      key: 'userInfo',
      group: [{
          key: 'street',
        },
        {
          key: 'phone',
        },
      ],
    },
    {
      key: 'fullName',
      group: [{
          key: 'firstName',
        },
        {
          key: 'lastName',
        },
      ],
    },
  ],
};

let res = [];
let idx = 0;

function iter(obj) {
  let key = obj.key;
  if (obj.group) obj.group.forEach(i => res.push(key   "."   i.key))
  idx  ;
  
  //base condition
  if (idx == data.data.length) return;
  
  iter(data.data[idx]);
}

iter(data.data[idx]);

console.log(res);
<iframe name="sif7" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Using flatMap and map in one iteration

const getPaths = (arr) =>
  arr.flatMap(({ key, group }) => group.map(({ key: k }) => `${key}.${k}`));

const data = {
  data: [
    {
      key: "userInfo",
      group: [
        {
          key: "street",
        },
        {
          key: "phone",
        },
      ],
    },
    {
      key: "fullName",
      group: [
        {
          key: "firstName",
        },
        {
          key: "lastName",
        },
      ],
    },
  ],
};

console.log(getPaths(data.data))
<iframe name="sif8" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related