I've got an array that I would like to remove some elements from. I can't use Array.prototype.filter()
, because I want to modify the array in place (because it saves a memory allocation and, more important for me, makes the code more simple in my use case). Is there an in-place alternative to filter
that I can use, maybe analogously to how Array.prototype.forEach()
can be used as an in-place variant to Array.prototype.map()
?
Edit: Minimum example upon request:
function someCallback(array) {
// do some stuff
array.filterInPlace(function(elem) {
var result = /* some logic */
return result;
})
// do some more stuff
}
Is there an in-place alternative to filter
No, but it's not hard to write your own. Here is an approach which squeezes out all the values which fail a condition.
function filterInPlace(a, condition) {
let i = 0, j = 0;
while (i < a.length) {
const val = a[i];
if (condition(val, i, a)) a[j++] = val;
i++;
}
a.length = j;
return a;
}
condition
is designed to have the same signature as the callback passed to Array#filter
, namely (value, index, array)
. For complete compatibility with Array#filter
, you could also accept a fourth thisArg
parameter.
forEach
Using forEach
has the minor advantage that it will skip empty slots. This version:
thisArg
function filterInPlace(a, condition, thisArg) {
let j = 0;
a.forEach((e, i) => {
if (condition.call(thisArg, e, i, a)) {
if (i!==j) a[j] = e;
j++;
}
});
a.length = j;
return a;
}
a = [ 1,, 3 ];
document.write('<br>[',a,']');
filterInPlace(a, x=>true);
document.write('<br>[',a,'] compaction when nothing changed');
b = [ 1,,3,,5 ];
document.write('<br>[',b,']');
filterInPlace(b, x=>x!==5);
document.write('<br>[',b,'] with 5 removed');