The usual answer here is to loop backward, or if you have to loop forward, keep track of how many you've removed and adjust the index you're checking accodringly. But, in both cases, you'll still be doing multiple passes through the array, because splice
itself is a loop — it has to loop from the index you're deleting at right the way to the end of the array, moving the entries around.
So the other usual answer is: Use filter
, which makes a single pass. filter
creates a new array, but that's usually just fine.
If you have to modify the original array and you don't want multiple loops (some hidden away inside splice
), you can create your own operation instead that copies the elements necessary as it goes, in a single pass:
function removeIndexes(array, indexes) {
let read = 0;
let write = 0;
while (read < array.length) {
if (!indexesOfArrayElementWhichMustBeRemoved.includes(read)) {
array[write++] = array[read];
}
++read;
}
if (read !== write) {
// Array got shorter
array.length = write;
}
return array;
}
Live Example:
const targetArray = [ "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india" ];
const indexesOfArrayElementWhichMustBeRemoved = [ 2, 5, 8 ];
function removeIndexes(array, indexes) {
let read = 0;
let write = 0;
while (read < array.length) {
if (!indexesOfArrayElementWhichMustBeRemoved.includes(read)) {
array[write++] = array[read];
}
++read;
}
if (read !== write) {
// Array got shorter
array.length = write;
}
return array;
}
removeIndexes(targetArray, indexesOfArrayElementWhichMustBeRemoved);
console.log(targetArray);
For completeness, here's going backward:
for (let index = targetArray.length - 1; index >= 0; --index) {
if (indexesOfArrayElementWhichMustBeRemoved.includes(index)) {
targetArray.splice(index, 1); // Note that this is an inner loop
}
}
const targetArray = [ "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india" ];
const indexesOfArrayElementWhichMustBeRemoved = [ 2, 5, 8 ];
for (let index = targetArray.length - 1; index >= 0; --index) {
if (indexesOfArrayElementWhichMustBeRemoved.includes(index)) {
targetArray.splice(index, 1); // Note that this is an inner loop
}
}
console.log(targetArray);
and here's keeping track of how many you removed:
let removed = 0;
for (let index = 0; index < targetArray.length; ) {
if (indexesOfArrayElementWhichMustBeRemoved.includes(index + removed)) {
targetArray.splice(index, 1); // Note that this is an inner loop
++removed;
} else {
++index;
}
}
const targetArray = [ "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india" ];
const indexesOfArrayElementWhichMustBeRemoved = [ 2, 5, 8 ];
let removed = 0;
for (let index = 0; index < targetArray.length; ) {
if (indexesOfArrayElementWhichMustBeRemoved.includes(index + removed)) {
targetArray.splice(index, 1); // Note that this is an inner loop
++removed;
} else {
++index;
}
}
console.log(targetArray);
and here's filter
:
const replacement = targetArray.filter((_, index) => !indexesOfArrayElementWhichMustBeRemoved.includes(index));
const targetArray = [ "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india" ];
const indexesOfArrayElementWhichMustBeRemoved = [ 2, 5, 8 ];
const replacement = targetArray.filter((_, index) => !indexesOfArrayElementWhichMustBeRemoved.includes(index));
console.log(replacement);