3

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?

5 Answers 5

5

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--;
 }
}
Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

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

Comments

1

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

Comments

0

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

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.