How can I remove a specific item from an array?


I have an array of numbers, and I'm using the .push() method to add elements to it.

Is there a simple way to remove a specific element from an array?

The equivalent of something like -

array.remove(number);

I have to use core JavaScript - frameworks are not allowed.

Performance

Today (2019-12-09) I conduct performance tests on macOS v10.13.6 (High Sierra) for chosen solutions. I show delete (A), but I not use it in comparison with other methods, because it left empty space in the array.

The conclusions

  • the fastest solution is array.splice (C) (except Safari for small arrays where it has the second time)
  • for big arrays, array.slice+splice (H) is the fastest immutable solution for Firefox and Safari; Array.from (B) is fastest in Chrome
  • mutable solutions are usually 1.5x-6x faster than immutable
  • for small tables on Safari, surprisingly the mutable solution (C) is slower than the immutable solution (G)

Details

In tests I remove middle element from the array in different ways. The A, C solutions are in-place. The B, D, E, F, G, H solutions are immutable.

Results for array with 10 elements

Enter image description here

In Chrome the array.splice (C) is the fastest in-place solution. The array.filter (D) is the fastest immutable solution. The slowest is array.slice (F). You can perform the test on your machine here.

Results for array with 1.000.000 elements

Enter image description here

In Chrome the array.splice (C) is the fastest in-place solution (the delete (C) is similar fast - but it left an empty slot in the array (so it does not perform a 'full remove')). The array.slice-splice (H) is the fastest immutable solution. The slowest is array.filter (D and E). You can perform the test on your machine here.

var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var log = (letter,array) => console.log(letter, array.join `,`);

function A(array) {
  var index = array.indexOf(5);
  delete array[index];
  log('A', array);
}

function B(array) {
  var index = array.indexOf(5);
  var arr = Array.from(array);
  arr.splice(index, 1)
  log('B', arr);
}

function C(array) {
  var index = array.indexOf(5);
  array.splice(index, 1);
  log('C', array);
}

function D(array) {
  var arr = array.filter(item => item !== 5)
  log('D', arr);
}

function E(array) {
  var index = array.indexOf(5);
  var arr = array.filter((item, i) => i !== index)
  log('E', arr);
}

function F(array) {
  var index = array.indexOf(5);
  var arr = array.slice(0, index).concat(array.slice(index + 1))
  log('F', arr);
}

function G(array) {
  var index = array.indexOf(5);
  var arr = [...array.slice(0, index), ...array.slice(index + 1)]
  log('G', arr);
}

function H(array) {
  var index = array.indexOf(5);
  var arr = array.slice(0);
  arr.splice(index, 1);
  log('H', arr);
}

A([...a]);
B([...a]);
C([...a]);
D([...a]);
E([...a]);
F([...a]);
G([...a]);
H([...a]);
This snippet only presents code used in performance tests - it does not perform tests itself.

Comparison for browsers: Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0

Enter image description here


ES10 Update

This post summarizes common approaches to element removal from array as of ECMAScript 2019 (ES10).

1. General cases

1.1. Removing Array element by value using .splice()

| In-place: Yes |
| Removes duplicates: Yes(loop), No(indexOf) |
| By value / index: By index |

If you know the value you want to remove from an array you can use the splice method. First you must identify the index of the target item. You then use the index as the start element and remove just one element.

// With a 'for' loop
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
for( let i = 0; i < arr.length; i++){
  if ( arr[i] === 5) {
    arr.splice(i, 1);
  }
} // => [1, 2, 3, 4, 6, 7, 8, 9, 0]

// With the .indexOf() method
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
const i = arr.indexOf(5);
arr.splice(i, 1); // => [1, 2, 3, 4, 6, 7, 8, 9, 0]

1.2. Removing Array element using the .filter() method

| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |

Specific element can be filtered out from array, by providing filtering function. Such function is then called for every element in array.

const value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]

1.3. Removing Array element by extending Array.prototype

| In-place: Yes/No (Depends on implementation) |
| Removes duplicates: Yes/No (Depends on implementation) |
| By value / index: By index / By value (Depends on implementation) |

Prototype of Array can be extended with additional methods. Such methods will be then available to use on created arrays.

Note: Extending prototypes of objects from standard library of JavaScript (like Array) is considered by some as an antipattern.

// In-place, removes all, by value implementation
Array.prototype.remove = function(item) {
    for (let i = 0; i < this.length; i++) {
        if (this[i] === item) {
            this.splice(i, 1);
        }
    }
}
const arr1 = [1,2,3,1];
arr1.remove(1) // arr1 equals [2,3]

// Non-stationary, removes first, by value implementation
Array.prototype.remove = function(item) {
    const arr = this.slice();
    for (let i = 0; i < this.length; i++) {
        if (arr[i] === item) {
            arr.splice(i, 1);
            return arr;
        }
    }
    return arr;
}
let arr2 = [1,2,3,1];
arr2 = arr2.remove(1) // arr2 equals [2,3,1]

1.4. Removing Array element using the delete operator

| In-place: Yes |
| Removes duplicates: No |
| By value / index: By index |

Using the delete operator does not affect the length property. Nor does it affect the indexes of subsequent elements. The array becomes sparse, which is a fancy way of saying the deleted item is not removed but becomes undefined.

const arr = [1, 2, 3, 4, 5, 6];
delete arr[4]; // Delete element with index 4
console.log( arr ); // [1, 2, 3, 4, undefined, 6]

The delete operator is designed to remove properties from JavaScript objects, which arrays are objects.

1.5. Removing Array element using Object utilities (>= ES10)

| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |

ES10 introduced Object.fromEntries, which can be used to create desired Array from any Array-like object and filter unwanted elements during the process.

const object = [1,2,3,4];
const valueToRemove = 3;
const arr = Object.values(Object.fromEntries(
  Object.entries(object)
  .filter(([ key, val ]) => val !== valueToRemove)
));
console.log(arr); // [1,2,4]

2. Special cases

2.1 Removing element if it's at the end of the Array

2.1.1. Changing Array length

| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |

JavaScript Array elements can be removed from the end of an array by setting the length property to a value less than the current value. Any element whose index is greater than or equal to the new length will be removed.

const arr = [1, 2, 3, 4, 5, 6];
arr.length = 5; // Set length to remove element
console.log( arr ); // [1, 2, 3, 4, 5]
2.1.2. Using .pop() method

| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |

The pop method removes the last element of the array, returns that element, and updates the length property. The pop method modifies the array on which it is invoked, This means unlike using delete the last element is removed completely and the array length reduced.

const arr = [1, 2, 3, 4, 5, 6];
arr.pop(); // returns 6
console.log( arr ); // [1, 2, 3, 4, 5]

2.2. Removing element if it's at the beginning of the Array

| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |

The .shift() method works much like the pop method except it removes the first element of a JavaScript array instead of the last. When the element is removed the remaining elements are shifted down.

const arr = [1, 2, 3, 4];
arr.shift(); // returns 1
console.log( arr ); // [2, 3, 4]

2.3. Removing element if it's the only element in the Array

| In-place: Yes |
| Removes duplicates: N/A |
| By value / index: N/A |

The fastest technique is to set an array variable to an empty array.

let arr = [1];
arr = []; //empty array

Alternatively technique from 2.1.1 can be used by setting length to 0.