loading...
Cover image for 5 ways to delete an element from an array in JavaScript

5 ways to delete an element from an array in JavaScript

ip127001 profile image Rohit Kumawat ・2 min read

Situation:
Whenever we need to delete an element from an array based on index or certain condition, we can use following 5 ways.

  • [1] Array pop() method:-

This removes the last element from original array.

let numbers = [1,2,3,4,5]

let result = numbers.pop()

result: 5
numbers: [1,2,3,4]

pop() method returns the deleted value and remove that value from the original array.


  • [2] Array shift() method:- This removes the first element from original array.
let numbers = [1,2,3,4,5]

let result = numbers.shift()

result: 1
numbers: [2,3,4,5]

shift() methods returns the deleted value and remove that value from the original array.


  • [3] Array splice() method:- This removes specific element based on given index.[Example⬇️]

[3.1] With indexOf() method

let fruits = ['orange', 'mango', 'banana'];

//first find the index of element to be removed.
let index = fruits.indexOf('mango') // 1

//now use splice() method
let result = fruits.splice(index, 1); // ['mango']

fruits: ['orange', 'banana'] //element removed from original array

[3.2] With findIndex() method

let fruits = ['orange', 'mango', 'banana'];

//first find the index of element to be removed based on any condition
const index = fruits.findIndex(element => element === 'mango'); // 1

//now use splice() method
const result = fruits.splice(index, 1); // ['mango']

fruits: ['orange', 'banana'] //element removed from original array

splice() takes two optional parameters first being index of element to be deleted and second is number of elements to be deleted. In our case we just wanted to remove one element so we passed 1 as second parameter.

findIndex() provide callback function which will be executed on each element of array unless it returns true based on your condition and returns the index of element truthy condition.


  • [4] Array filter() method:- This method returns the new array with elements that passes a particular condition passed in callback function i.e. filtering elements.[Example⬇️]
let numbers = [1,2,3,4,5];

let result = numbers.filter(el => el === 3);

result: [3] // returns the new array that elements that passed the condition in callback function
numbers: [1,2,3,4,5] // doesn't change the original array

  • [5] JavaScript delete operator- delete operator remove the element from the array but it creates a empty space or kind of hold in the array.[Example⬇️]
let numbers = [1,2,3,4,5];

delete numbers[2];

numbers: [1,2,empty,4,5] //chrome dev tools prints empty for the deleted value

numbers[2] // undefined but numbers[2] is not an undefined value

delete operator doesn't change the length of the array or the index position of elements and also creates an empty slot.

If you still want to use this approach, then assign undefined to the element instead using delete operator. [Example⬇️]

let numbers = [1,2,3,4,5];

numbers[2] = undefined;

numbers: [1,2,undefined,4,5] // this doesn't create an empty slot.

Conclusion:

I mostly use splice() with findIndex() to delete an element because during development because we generally have an condition based on which we have to delete an element from an array.

Thanks for reading!
Any feedback is welcome. Twitter

Posted on by:

ip127001 profile

Rohit Kumawat

@ip127001

Helping startups to build world class products. I love web, Javascript and F.R.I.E.N.D.S.

Discussion

markdown guide
 

About your conclussion, I would suggest to try to avoid using splice mainly because it changes the original array, and if you need it in other places, it could mess things up (is better to avoid mutations). If I had to "delete" an element from an array, I would go with the filter approach:

/** Curried filter out util */
const filterOut = filterer => source => source.filter(item => !filterer(item));
/** Filter out items with the value 3 */
const filterOut3 = filterOut(item => item === 3)

const original = [0, 1, 2, 3, 4];
const filtered = filterOut3(original);
console.log(filtered); // [0, 1, 2, 4]
console.log(original); // original is still intact: [0, 1, 2, 3, 4]
 

Hmmm, splice is fine...

Const _copy = x.slice()
_copy.splice(y, 1)
Return _copy

Concise, easy to understand, immutable.

 

I don't agree much in the "easy to understand" part, if I read that it says: Assign a slice of x to _copy, but with no params so is a copy... then run splice on that copy... and return it.

I have to actually "think" about what you're trying to do. You could use spread to generate the copy, which makes the copy intent more clear. Not only that, in my example, the idea is that it supports a filterer function, so if we make your code match the logic it looks like this:

const filterOut = filterer => source => {
  const copy = [...source]; // Create a copy of source
  const index = copy.findIndex(filterer); // Look for the index
  if (index >= 0) { // We have tom make sure is not -1
    copy.splice(index, 1); // Splice the copy.
  }
  return copy; // Return the copy
}

And to achieve the same just using filter:

const filterOut = filterer => source =>
  source.filter(item => !filterer(item)); // Filter the source. Done.

Not sure how spread makes it more clear?!?! Array.prototype.slice is literally intended and is know to make a copy of an array....

From MDN:

The slice() method returns a shallow copy of a portion of an array into a new array object selected from start to end (end not included) where start and end represent the index of items in that array. The original array will not be modified.

Using the spread operator in no way marks an intent to copy. The only thing that says that in your code is the comment. 🤣

And if you understand splice, it modifies the array in place....

so, three operations:

COPY : const _copy = x.slice()
DELETE: _copy.splice(y, 1)
RETURN

It's pretty damn easy to understand. Wrap it in a function if you want safelyDeleteFromArrayAtIndex(array, index)

I said I don't agree, I'm not saying "the standard doens't agree" or something like that. From my personal point of view, spread clearly states "copy" when used like [...array], while slice could mean you want a piece of an array, but when no params are given, it gives you the entire array.

Basically, I read array.slice() as JS does: "give me a portion of array, and that portion is from end to beggining", while I read [...array] as "give me a copy of array".

And while I agree is better to abstract those behaviors in functions, the code inside functions ideally should be super easy to read to anyone (mainly if you work with others). Taking that into consideration, I think using filter is clearer than using slice and splice.

And as I mentioned in my previous reply, your code doesn't do the same as mine, you need to add the findIndex logic to match, if you don't like the spread there, it still needs to look something like this:

const filterOut = filterer => source => {
  const copy = source.slice();
  const index = copy.findIndex(filterer);
  if (index >= 0) {
    copy.splice(index, 1);
  }
  return copy;
}

Which is still more complex than just doing filter. Finally: I dind't added the comments to explain the spread (is self explinatory), I added the comments to show you that there are 4 steps to achieve what you can achieve in just one.

Oh, I know you said you don't agree. And I don't agree. Like you said, your point of view.

Given that the definition of slice is to copy the array and should be used as such, I would expect it to be easier to understand, than say, using the spread operator, which is while is your preferred method, respectfully I disagree it's the clearest.

the filter method is used for a boolean comparison on condition and whilst it's a novel usage, is also not clear that it is being used to delete an item and would require inspection of code

Your original comment was about not using splice, I said it's fine. That's all I came here to say.

I mean, I appreciate you fancy use of currying to create ANY condition for deletion, but the original post was about deleting an object an index.

 

Hah, interesting,you rather create whole new array than delete some elements. For every method, use with care,dude, you don't want memory leak or any other issue

 

Immutability doesn't generate memory leaks. Basically, you never change anything, you just create new things with the differences on them. Google about immutability and functional programming, trust me, it makes the code easier to maintain and less pron to errors.

I know the concepts, now you please google mem leak in js. Functional programming sounds like sugar at first but you will hit performance issues. It's a trace off. filter() is a method to create new array from the existing once. Here if you and the post owner want to make it a way of delete, it will be reassigning after filtering.

Immutability doesn't have anything to do with memory leaks, mutation does. Immutability does take more space in memory sometimes, yes. But a leak means that you mess up with the garbage colector, which doesn't happen when you avoid mutations altogether 😃

const immutableAddLast = item => array => [...array, item];
const badAddLast = item => array => array.push(item);

const original = [0, 1, 2, 3, 4];

// We call `immutableAddLast` 100000 times:
[...(new Array(1e5))].map((_, index) => immutableAddLast(item)(original));
// Memory is freed after this computes because we didn't changed original

// We call `badAddLast` 100000 times:
[...(new Array(1e5))].map((_, index) => badAddLast(item)(original));
// We mutated the `original` array and added 100000 items to it

When you work with immutability, you create new copies of the pre-existing data, but if you don't use the original any longer, it gets garbage collected, and the same happen with the copies, so no memory leaks.

On the contrary, if you mutate pre-existing structures, those stay in memory, and in top of that the content of the original structure is unpredictable, ergo harder to maintain, debug and extend.

Dude, you went too far. I was talking about the performance. When you said "a leak means that you mess up with the garbage collector", I know you wouldn't care enough. Leak in JS can be very simple that you create and hold too much memory but don't release them after used, or maybe global mem. Do you even know that the two example you gave are totally different in logic? One is creating 6-elem array many times, one is appending many elements in a single array. It depends on the developer's need, he can either modify or clone the original array. If he needs handy, your way will be better because of least effort (still wrong in logic in that example). If he needs performance, go the other way. If he wants to preserve the original array, then clone, if not, do on the current existing one, release it eventually.

It was an example to illustrate that adding an element to an array with the immutable approach just returns a copy of the array with the new element, while the other approach changes the original array, is not a piece or production ready code 🤣.

They obviously behave differently, because that's part of the point of the example, if they did the same there would be nothing to discuss. The example shows how something as innocent as adding a new item into an array could be disastrous when using push (impure) vs doing a copy of the array with the new element (pure).

I understand your point, from your PoV "it depends":

  • Do mutations when you're sure™️ there will be no issues with that.
  • Avoid mutations when you need to avoid changing the original.

From my PoV you should always avoid mutations, because I prefer to rely on certainties instad of relying on "maybes", and when using mutations you always "might" change something you should't. As I explained before, the copies of the data get removed from memory if not used (JavaScript has a garbage collector, it isn't ANSI C), and if your main concern is that the data you're loading in the UI is too heavy to do copies, then the problem is in the volume of data you're loading, not the way you're handling it.

You are driving the discussion. I barely talk about the language and performance. You are uncertain in something doesn't mean every body is. I said it depends for a reason. Let's take a simple example, create an array contain the first 1000000 natural numbers. My take will be for and push. It is straight forward enough. Js has GC doesn't mean that you should abuse it. Your way of copying data is not suitable for data processing where performance is crucial. Period. Don't be obsessed and you should be aware of it pros and cons. And please don't expect everyone has same coding style as yours. I can accept the beautiful of FP why don't you accept its ugly?

Han, take a look at my first messages. I started with "I suggest", a suggestion is not "expecting everyone has the same coding style", is showing something that the author maybe missed or wasn't aware off.

I'm not driving the discussion, I'm trying to be as clear as possible about the reasoning behind my suggestion. I'm not the one that replied with a "hah" and a remark about how immutability can lead to memory leaks.

And about your example, as I mentioned in my previous reply:

If your main concern is that the data you're loading in the UI is too heavy to do copies, then the problem is in the volume of data you're loading, not the way you're handling it.

That includes your array of 1000000 natural numbers.

 

Thanks for the cool suggestion and I have mentioned the filter() method also.
But yeah when immutability comes in picture you should always use methods which returns new arrays and doesn't affect original one.
Use deep cloning for objects or arrays passed as props if you still want to directly change the prop like using splice().

 

Indeed! The best library out there to work with immutability is immer, because it allows the dev to code with immutablility, and use the mutable style, so you end up "having the cake and eating it too".

I will surely check it out!

 

Splice has its place, same as immutable approaches.

 

It does indeed. My suggestion is based on the fact that the autor mentioned that he mostly uses splice, when is generally better to try to avoid it (avoid doesn't mean "never use", it justs means think twice before using it, there might be a better approach to the same problem).

 

Great info thanks.

Perhaps it’s also useful to highlight which method creates a copy of the array, and which ones alters the original array. I mean I can tell by reading the code, but thought it should be highlighted since it’s one of the main consideration to choosing a method. The others being speed (which can be subjective and requires more elaboration, but definitely makes it more informative), and readability (self explanatory).

For example, the delete operator iirc is slow and most of the time assigning to undefined or null is better if the use-case allows.

 

Great suggestion! I will surely add the information about mutability and immutability.

 

Another quick way is using the length property to your advantage.

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

Poof! The last three elements are gone.

 

Thanks for reading and a great suggestion!

 

This indeed is the fastest! 😂

 

[3.2] With findIndex() method

Mistake :
You declared a fruit array but you get the index from an undefined numbers array.

 

Thanks for reading the article and pointing out the mistake.