Search multidimentional array for an object with a matching value

Viewed 62

How would I go about searching a multidimensional array for a value and then delete the object where the value was found, the code below will not always be the same so i need a way to search all of the arrays to find the object with a specific value

For example, if I wanted to delete an object with the id of 8, how would I search all arrays and objects for the id and then delete the object, here is an example of the data

{
  MenuLocation: 'Jersey',
  MenuItems: [
    {
      id: '1',
      parentId: '1',
      position: 2,
      name: 'test1',
      link: 'http://google.com',
      submenu: []
    },
    {
      id: '2',
      parentId: '2',
      position: 1,
      name: 'test2',
      link: '#',
      submenu: [
        {
          id: '3',
          parentId: '2',
          position: 1,
          name: 'testsub1',
          link: 'http://google.com',
          submenu: []
        },
        {
          id: '4',
          parentId: '2',
          position: 2,
          name: 'testsub2',
          link: 'http://google.com',
          submenu: [
            {
              id: '5',
              parentId: '4',
              position: 1,
              name: 'testsub4.1',
              link: 'http://google.com',
              submenu: []
            },
            {
              id: '6',
              parentId: '4',
              position: 2,
              name: 'testsub4.2',
              link: 'http://google.com',
              submenu: []
            },
            {
              id: '7',
              parentId: '4',
              position: 3,
              name: 'testsub4.3',
              link: 'http://google.com',
              submenu: [
                {
                  id: '8',
                  parentId: '7',
                  position: 3,
                  name: 'testsub4.1',
                  link: 'http://google.com',
                  submenu: []
                },
                {
                  id: '9',
                  parentId: '7',
                  position: 2,
                  name: 'testsub4.2',
                  link: 'http://google.com',
                  submenu: []
                },
                {
                  id: '10',
                  parentId: '7',
                  position: 1,
                  name: 'testsub4.3',
                  link: 'http://google.com',
                  submenu: []
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

This is what I've put together so far, it's quite messy but it works but I assume this is not the best way to do it

 delClick(id) {


for (var key in this.menu.MenuItems) {
  var obj = this.menu.MenuItems[key];
  if (obj.id == id) {
    console.log('match');
  } else {
    if (obj.submenu.length > 0) {
      for (var key in obj.submenu) {
        var nextobj = obj.submenu[key];
        if (nextobj.id == id) {
          console.log('match');
          console.log(nextobj);
        } else {
          for (var key in nextobj.submenu) {
            var objn = nextobj.submenu[key]
            if (objn.id == id) {
              console.log('match');
              console.log(objn);
            }
          }
        }
      }

    }

  }

}

} }

I would have to keep adding for loops until it checks everything but I don't know how many arrays and objects there will be, what is the best way to overcome this?

1 Answers

This is a little bit more complex because once you delete items you need to update their position.

A simple but naive way would be to compute a flat list of items, turn that into a map. Get the parent item by its parentId and delete the sub item based on its position, then update the position in the submenu.

function toValues (data) {
    const obj = data.MenuItems || data.submenu;
    if (obj && typeof obj === 'object') {
        const values = Object.values(obj);
        return values.concat(values.map(toValues)).flat();
    }
    return obj;
}
function toLkp (data) {
    return toValues(data).reduce((acc, cur) => {
        acc[cur.id] = cur;
        return acc;
    }, {});
}
function del (id, data) {
    const lkp = toLkp(data);
    const obj = lkp[id];
    const par = lkp[obj.parentId];
    const pos = obj.position;

    par.submenu.splice(obj.position - 1, 1);
    for (const itm of par.submenu) {
        if (itm.position > pos) itm.position -= 1;
    }
    return data;
}

console.log (JSON.stringify(data));

del(3, data);

console.log (JSON.stringify(data));
<script>
var data  = {
    MenuLocation: 'Jersey',
    MenuItems: [{
            id: '1',
            parentId: '1',
            position: 2,
            name: 'test1',
            link: 'http://google.com',
            submenu: []
        },
        {
            id: '2',
            parentId: '2',
            position: 1,
            name: 'test2',
            link: '#',
            submenu: [{
                    id: '3',
                    parentId: '2',
                    position: 1,
                    name: 'testsub1',
                    link: 'http://google.com',
                    submenu: []
                },
                {
                    id: '4',
                    parentId: '2',
                    position: 2,
                    name: 'testsub2',
                    link: 'http://google.com',
                    submenu: [{
                            id: '5',
                            parentId: '4',
                            position: 1,
                            name: 'testsub4.1',
                            link: 'http://google.com',
                            submenu: []
                        },
                        {
                            id: '6',
                            parentId: '4',
                            position: 2,
                            name: 'testsub4.2',
                            link: 'http://google.com',
                            submenu: []
                        },
                        {
                            id: '7',
                            parentId: '4',
                            position: 3,
                            name: 'testsub4.3',
                            link: 'http://google.com',
                            submenu: [{
                                    id: '8',
                                    parentId: '7',
                                    position: 3,
                                    name: 'testsub4.1',
                                    link: 'http://google.com',
                                    submenu: []
                                },
                                {
                                    id: '9',
                                    parentId: '7',
                                    position: 2,
                                    name: 'testsub4.2',
                                    link: 'http://google.com',
                                    submenu: []
                                },
                                {
                                    id: '10',
                                    parentId: '7',
                                    position: 1,
                                    name: 'testsub4.3',
                                    link: 'http://google.com',
                                    submenu: []
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}
</script>

As you can see in the console.log, the item with the id 3 is gone and the item with the id 4 has a position of 1.

Related