jvc26
jvc26

Reputation: 6503

How to remove multiple items from an array via looping in Javascript

So, I have a javascript array of multiple values:

var keymap = {'name': 'foobaz', 
              'mappings': [{'id': 1, 'key': 'b'},
                          {'id': 2, 'key': 'c'},
                          {'id': 3, 'key': 'd'},
                          {'id': 1, 'key': 'e'},
                          {'id': 10, 'key': 'f'},
                          {'id': 7, 'key': 'g'},
                          {'id': 1, 'key': 'h'}]
}

I want to remove any entries where key is 'b'. Note the ids correspond to the backend ids. What I want to do is to remove some of the mappings (for example, all with 'id' as '1').

What I've tried is:

for (var i = 0; i < keymap['mappings'].length; i++) {
    if (keymap['mappings'][i]['id'] === id_to_match) {
        keyboard_map['mappings'].splice(i, 1);
    }
}

However, slice will change the indexes of the array in-place, and therefore now i won't point to the correct index point (as any indexes higher will now be i-n where n would be the number of slices done before.

What is the correct way to implement this?

Upvotes: 3

Views: 148

Answers (5)

ZER0
ZER0

Reputation: 25322

I would use the filter method:

var id_to_remove = 1;
keymap.mappings = keymap.mappings.filter(function(item) {
    return item.id !== id_to_remove;
}));

Notice that, besides using the filter method or not, even with a plain for loop, is much better for performance create a new array from scratch, instead of mutate the current one multiple times. So basically:

var id_to_remove = 1;
var filtered = [];
for (var i = 0, item; item = keymap.mappings[i++];) {
    if (item.id !== id_to_remove)
        filtered.push(item);
}
keymap.mappings = filtered;

Of course if filter is available it's much better use it because it's native, here we just mimic the same behavior.

Upvotes: 2

VladimirKosmala
VladimirKosmala

Reputation: 62

You can use the "filter" method like this:

keymap.mappings = keymap.mappings.filter(function(element){
    return element.id != 1;
});

Which means "keep only elements with id different than 1" or same result "remove elements with id equal to 1".

Every browser implement it, except IE8. http://kangax.github.io/es5-compat-table/#Array.prototype.filter

Upvotes: 0

Scott Mermelstein
Scott Mermelstein

Reputation: 15397

You could walk your array backwards, so that the splicing doesn't impact later loop iterations:

for (var i = keymap['mappings'].length - 1; i >= 0; i--) {
    if (keymap['mappings'][i]['id'] === id_to_match) {
        keyboard_map['mappings'].splice(i, 1);
    }
}

Upvotes: 1

Nicolas Straub
Nicolas Straub

Reputation: 3411

for (var i = 0; i < keymap['mappings'].length; i++) {
    if (keymap['mappings'][i]['id'] === id_to_match) {
        keyboard_map['mappings'].splice(i--, 1);
    }
}

Upvotes: 1

Travis J
Travis J

Reputation: 82267

An easy way is to decrement the iterator (this works since you read the length every iteration - so make sure you avoid caching the length)

for (var i = 0; i < keymap['mappings'].length; i++) {
 if (keymap['mappings'][i]['id'] === id_to_match) {
    keyboard_map['mappings'].splice(i, 1);
    i--;
 }
}

Upvotes: 5

Related Questions