简体   繁体   中英

Remove every object inside the array

I'm trying to delete all matched items from an array but it leaves Always one item in it.

var item1 = {item: "item1"},
    array = [{
        item: "item1"},{
        item: "item_non"},{
        item: "item1"},{
        item: "item_non"},{
        item: "item1"},{
        item: "item1"},{
        item: "item1"},{
        item: "item_non"},{
        item: "item_non"
    }];
array.forEach(function(items){
    if(item1.item === items.item){
        var index = array.indexOf(items);
        if(index !== -1){
            array.splice(index,1);
        }
    }
});

I also fiddle it, it deletes only 4/5 items that matches instead of 5/5.

Fiddle

There is no option to use Array#filter I need to delete the objects.

The problem is that .splice() moves all the elements after the deleted element down. So if you delete element 3, element 4 becomes 3, 5, becomes 4, and so on. The next iteration of the loop will process element 4, but that's the original element 5 -- the original element 4 is skipped.

The way to solve this is to process the array in reverse. .forEach can't do this, AFAIK, so you have to use a for loop:

for (var i = array.length - 1; i >= 0; i--) {
    item = array[i];
    if (item1.item == item.item) {
        array.splice(i, 1);
    }
}

Here's another version that does in-place manipulation of the array.

http://codepen.io/anon/pen/XmZrww?editors=001

// remove the matching item and return the array
var filterArray = function (arr, obj) {
  for (var i = 0, len = arr.length; i < len; i++) {
    if (arr[i].item === obj.item) {
      arr.splice(i, 1);
      len--;
      i--;
    }
  }
  return arr;
};

var item1 = {item: "item1"};
var data = [
  {item: "item1"},
  {item: "item_non"},
  {item: "item1"},
  {item: "item_non"},
  {item: "item1"},
  {item: "item1"},
  {item: "item1"},
  {item: "item_non"},
  {item: "item_non"}
];

console.log(filterArray(data, item1));

Here's my version http://codepen.io/anon/pen/VvQZVe?editors=001

Note I cleaned up the code a bit.

Repeatedly using indexOf in a loop is expensive. The worst case for doing that in a big array is having to go to almost the end of the loop many times.

This version potentially uses almost 2x the memory (imagine a big array where there's only a single item to be removed). But, its faster.

// indexOf is expensive, especially in a loop.
// here we just iterate straight through the array and append
// mismatching properties to another array that gets returned.
var filterArray = function (arr, obj) {
  var returnArray = [];

  arr.forEach(function (el) {
    if (el.item !== obj.item) {
      returnArray.push(el);
    }
  });

  return returnArray;
};

var item1 = {item: "item1"};
var data = [
  {item: "item1"},
  {item: "item_non"},
  {item: "item1"},
  {item: "item_non"},
  {item: "item1"},
  {item: "item1"},
  {item: "item1"},
  {item: "item_non"},
  {item: "item_non"}
];

console.log(filterArray(data, item1));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM