Find an object in array based on array of values then remove them

I need to find an object in array based on array of values and then remove them, this was easy when I only needed to find one item, I did it like this:

if (mdl.findObjectByKey(response, 'cat_id', 171) == true) {
  console.log("item removed from dropdown");
  var catId = response.map(item => item.cat_id).indexOf(171);
  response.splice(catId, 1);
}

This would remove the item with a cat_id === 171 from the array of objects.

Now I need to remove more items so it would look something like this:

var itemsToRemove = [171, 182, 199, 234];
if (mdl.findObjectByKey(response, 'cat_id', itemsToRemove) == true) {
  console.log("item removed from dropdown");
  var catId = response.map(item => item.cat_id).indexOf(itemsToRemove);
  response.splice(catId, 1);
}

Obviously, the above example does not work at all, I just wanted to explain what I needed.

2 answers

  • answered 2018-03-13 20:21 Mike C

    As you've found out, you can't just pass an array of numbers to a function that wants a single number. Instead, you can utilize a for loop and iterate through each of the numbers.

    var itemsToRemove = [171, 182, 199, 234];
    for (var i = 0; i < itemsToRemove.length; i++) {
      var id = itemsToRemove[i];
      if (mdl.findObjectByKey(response, 'cat_id', id) == true) {
        var catId = response.map(item => item.cat_id).indexOf(item);
        response.splice(catId, 1);
      }
    }
    

    or using a for..of loop (and some other newer niceties):

    const itemsToRemove = [171, 182, 199, 234];
    for (let id of itemsToRemove) {
      if (mdl.findObjectByKey(response, 'cat_id', id)) {
        let catId = response.map(item => item.cat_id).indexOf(item);
        response.splice(catId, 1);
      }
    }
    

  • answered 2018-03-13 20:21 doodle meister

    You're doing multiple passes just to remove a single object. You certainly don't want to keep it that way, much less duplicate all those passes for each key to remove.

    Just filter the collection down to those without the keys to remove. Use a Set to avoid a repeated linear search.

    var itemsToRemove = new Set([171, 182, 199, 234]);
    var filtered = response.filter(obj => !itemsToRemove.has(obj.cat_id));
    

    If you need to mutate the original collection, you can then copy it over.

    filtered.forEach((obj, i) => response[i] = obj);
    response.length = filtered.length;
    

    You could also do the above in a single pass by copying the objects to keep into the current index of the original array, minus an offset for the number of removed items. Then just adjust the length at the end.