Austin
Austin

Reputation: 335

Get value from nested arrays of objects

I have data that is structured like the following:

const arr = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
        id: 1,
        name: 'Redwood forest',
        icon: 'mdi-image-filter-hdr'
    }]
},{
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
        id: 8,
        name: 'Redwood',
        icon: 'mdi-pine-tree'
    }]
}];

The top level is an array of objects, and each object can have a child field children which itself can be an array of objects. If I know the value of id, how can I find the object (or more importantly the object name), based on that id value?

Upvotes: 0

Views: 3180

Answers (7)

Ram Rana
Ram Rana

Reputation: 204

One way is by using Array find() method

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

let object= arr.find((item)=>item.id === "your ID");
console.log(object?.name);

const arr = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
        id: 1,
        name: 'Redwood forest',
        icon: 'mdi-image-filter-hdr'
    }]
},{
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
        id: 8,
        name: 'Redwood',
        icon: 'mdi-pine-tree'
    }]
}];

let object= arr.find((item)=>item.id === 2);
console.log(object?.name);

let object= arr.find((item)=>item.id === "your ID");
console.log(object?.name);

Upvotes: 0

Siddharth
Siddharth

Reputation: 637

function findChildrenById(data, cid) {
  for (let p = 0; p < data.length; p += 1) {
    if (data[p].id === cid) return data[p].name
    let res = data[p].children.find(c => c.id === cid)
    if (res) return res.name
  }

  return null
}


const arr = [{
  id: 0,
  name: 'Biomes',
  icon: 'mdi-image-filter-hdr',
  isParent: true,
  children: [{
    id: 1,
    name: 'Redwood forest',
    icon: 'mdi-image-filter-hdr'
  }]
}, {
  id: 2,
  name: 'Trees',
  icon: 'mdi-pine-tree',
  children: [{
    id: 8,
    name: 'Redwood',
    icon: 'mdi-pine-tree'
  }]
}];

console.log(findChildrenById(arr, 2))

Upvotes: 0

Vadim
Vadim

Reputation: 543

First arg for child

Second arg for main

const arr = [
    {id: 0,name: 'Biomes',icon: 'mdi-image-filter-hdr',isParent: true,
    children: [{id: 1,name: 'Redwood forest',icon: 'mdi-image-filter-hdr',},],},
    {id: 2,name: 'Trees',icon: 'mdi-pine-tree',
    children: [{id: 8,name: 'Redwood',icon: 'mdi-pine-tree',},],},
];

const getChildById = (_id, _id2 = false)=>{
    for(const main of arr){
        if(_id2 !== false && main.id !== _id2)continue;
        for(const child of main.children){
            if(child.id === _id)return child;
        }
    }
    return false;
};

(async()=>{
    const i_want_this_id = 8;

    //

    const a = getChildById(i_want_this_id);
    console.log('Found', a);
})();

Upvotes: 0

DecPK
DecPK

Reputation: 25398

You can use recursion here to get the object no matter how deep it is. I've filtered out the object. It will only give the object without children property. You can include it in the way you want

function getObjectFromId(arr, id) {
  for (let i = 0; i < arr.length; ++i) {
    if (arr[i].id === id) {
     // return arr[i]   // If you want full object with children
      const { children, ...rest } = arr[i];
      return rest;
    }
    if (arr[i].children) {
      const result = getObjectFromId(arr[i].children, id);
      if (result) return result;
    }
  }
}

const arr = [
  {
    id: 0,
    name: "Biomes",
    icon: "mdi-image-filter-hdr",
    isParent: true,
    children: [
      {
        id: 1,
        name: "Redwood forest",
        icon: "mdi-image-filter-hdr",
      },
    ],
  },
  {
    id: 2,
    name: "Trees",
    icon: "mdi-pine-tree",
    children: [
      {
        id: 8,
        name: "Redwood",
        icon: "mdi-pine-tree",
        children: [
          {
            id: 9,
            name: "Redwood",
            icon: "mdi-pine-tree",
          },
        ],
      },
    ],
  },
];

function getObjectFromId(arr, id) {
  for (let i = 0; i < arr.length; ++i) {
    if (arr[i].id === id) {
      // return arr[i]   // If you want full object with children
      const { children, ...rest } = arr[i];
      return rest;
    }
    if (arr[i].children) {
      const result = getObjectFromId(arr[i].children, id);
      if (result) return result;
    }
  }
}

console.log(getObjectFromId(arr, 1));
console.log(getObjectFromId(arr, 8));
console.log(getObjectFromId(arr, 9));
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

navnath
navnath

Reputation: 3714

To find at parent and child level

const arr=[{id:0,name:'Biomes',icon:'mdi-image-filter-hdr',isParent:!0,children:[{id:1,name:"Redwood forest",icon:'mdi-image-filter-hdr'}]},{id:2,name:'Trees',icon:'mdi-pine-tree',children:[{id:8,name:"Redwood",icon:'mdi-pine-tree',}]}]

const res = arr.reduce((a,item)=>{
    const { children, ...i} = item; 
    a.push(...children, i);
    return a; 
},[]);

function findInData(id){
  return res.find(o=>o.id===id);
}

console.log(findInData(8)?.name);
console.log(findInData(2)?.name);

Upvotes: 0

Isaac
Isaac

Reputation: 12874

const arr = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
        id: 1,
        name: 'Redwood forest',
        icon: 'mdi-image-filter-hdr'
    }]
},{
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
        id: 0,
        name: 'whatever',
        icon: 'new-tree'
    },{
        id: 8,
        name: 'Redwood',
        icon: 'mdi-pine-tree'
    }]
}];

const findById = (id) => arr
    .filter(x => x.id === id || x.children.some(child => id === child.id))
    .map(y => ({...y, children: y.children.filter(child => id === child.id)}))

console.log(findById(0))

You can first filter out all parents who has the same id or if the parent has child with same id via some, which then using map to and filter to remove all children who don't have the id

Upvotes: 1

Tuan Dao
Tuan Dao

Reputation: 2805

Solution 1: 2 for loop.

const inputArray = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
      id: 1,
      name: "Redwood forest",
      icon: 'mdi-image-filter-hdr'
    }]
  },
  {
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
      id: 8,
      name: "Redwood",
      icon: 'mdi-pine-tree',
    }]
  }
];

console.log(findById(8));

function findById(id) {
  for (const parent of inputArray) {
    if (parent.id === id)
      return parent;     
    for (const child of parent.children)
      if (child.id === id)
        return child;
  }
  return null;
}

Solution 2: multiple nested level:

const inputArray = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
      id: 1,
      name: "Redwood forest",
      icon: 'mdi-image-filter-hdr'
    }]
  },
  {
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
      id: 8,
      name: "Redwood",
      icon: 'mdi-pine-tree',
      children: [{
        id: 12,
        name: "Test Level 2",
        icon: 'mdi-pine-tree',
        children: [{
          id: 13,
          name: "Test Level 3",
          icon: 'mdi-pine-tree',
        }]
      }]
    }]
  }
];

console.log(findById(13, inputArray));

function findById(id, array) {
  for (const parent of array) {
    if (parent.id === id)
      return parent;

    if ('children' in parent) {
      const result = findById(id, parent.children);
      if (result) return result;
    }
  }

  return null;
}

Upvotes: 0

Related Questions