0

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?

6
  • Will the id match a object in the parents and children or just the parents? Commented Oct 11, 2021 at 4:26
  • @bassxzero it will match one or the other. It could match any parent or any child object. Commented Oct 11, 2021 at 4:28
  • Does the nesting will be only one level or it can go deeper? Commented Oct 11, 2021 at 4:28
  • There can be multiple children with same Id? Commented Oct 11, 2021 at 4:29
  • For now just one level but I would prefer a solution that is extensible to N levels deep Commented Oct 11, 2021 at 4:29

7 Answers 7

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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; }

Comments

0

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;
}

2 Comments

This is indeed the perfect solution for only single level of nesting but won't work if it will go deeper? For now just one level but I would prefer a solution that is extensible to N levels deep
@decpk I added both solutions.
0

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);

Comments

0

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);
})();

Comments

0

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))

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.