Home > Software engineering >  Extract sub-object from nested object typescript
Extract sub-object from nested object typescript

Time:04-21

Is there a way to extract a sub-object from a nested object?

For example I have the following object:

[
  {
    id: 370,
    name: 'FY 2022',
    children: [
      {
        id: 371,
        name: 'Q1 2022',
        children: [
          {
            id: 409,
            name: 'Jan 2022',
          },
          {
            id: 410,
            name: 'Feb 2022',
          },
          {
            id: 411,
            name: 'Mar 2022',
          },
        ],
      },
    ],
  },
];

if I send in a function as a parameter the id to return me the object corresponding with that id.

For example if I give as parameter id = 371 to return me:

[
  {
    id: 371,
    name: 'Q1 2022',
    children: [
      {
        id: 409,
        name: 'Jan 2022',
      },
      {
        id: 410,
        name: 'Feb 2022',
      },
      {
        id: 411,
        name: 'Mar 2022',
      },
    ],
  },
];

or if I give the id = 410 to return:

 [
  {
    id: 410,
    name: 'Feb 2022',
  },
];

Thanks in advance!

CodePudding user response:

You can do something like this

const findById = (data, id) => {
 if(data.length === 0){
   return []
 }
 const el = data.find(d => d.id === id)
 if(el){
   return [el]
 }
 return findById(data.flatMap(d => d.children || []), id)
}


const data = [
  {
    id: 370,
    name: 'FY 2022',
    children: [
      {
        id: 371,
        name: 'Q1 2022',
        children: [
          {
            id: 409,
            name: 'Jan 2022',
          },
          {
            id: 410,
            name: 'Feb 2022',
          },
          {
            id: 411,
            name: 'Mar 2022',
          },
        ],
      },
    ],
  },
];

console.log(findById(data, 370))
console.log(findById(data, 409))
console.log(findById(data, 4090))

CodePudding user response:

This is one possible solution using recursion to achieve the desired objective.

Code Snippet

const findUsingId = (searchId, arr) => (
  [
    arr.find(({ id }) => id === searchId) ||
    findUsingId(searchId, (arr.flatMap(({ children }) => children))) ||
    -1
  ].flat()
);

const origArr = [{
  id: 370,
  name: 'FY 2022',
  children: [{
    id: 371,
    name: 'Q1 2022',
    children: [{
        id: 409,
        name: 'Jan 2022',
      },
      {
        id: 410,
        name: 'Feb 2022',
      },
      {
        id: 411,
        name: 'Mar 2022',
      },
    ],
  }, ],
}, ];

console.log('id: 371', findUsingId(371, origArr));

console.log('id: 410', findUsingId(410, origArr));

console.log('id: 370', findUsingId(370, origArr));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Explanation

  • First, wrap the potential result within an array [] and apply .flat() so it is not nested.
  • Check if id exists in the current array
  • If not, recursive-call for an array of all children of current
  • If still not found, hard-coded a -1 (may be replaced as "not found", as needed)

CodePudding user response:

You can create a recursive function to process the whole object until it finds the right one. If you want to do it with typescript I would also create an interface to define a structure of the object. The final result will be this:

 interface IObject = {
  id: number;
  name: string;
  children?: IObject[];
 }
 function find(yourObject: IObject[], id: number) : IObject {
  let result : IObject;
  for(const obj of yourObject){
   const {id : idObj, children} = obj;
   if(idObj === id){
    result = obj;
   }
   else if(children){
    result = find(children, id);
   }
   if(result){
    break;
   }
  }
  return result;
 }
  • Related