DEV Community

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 Updated on ・3 min read

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

  • [1] Array pop() method:-

This removes the last element from the original array.

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

let result = numbers.pop()

result: 5
numbers: [1,2,3,4]
Enter fullscreen mode Exit fullscreen mode

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


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

let result = numbers.shift()

result: 1
numbers: [2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

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


  • [3] Array splice() method:- This removes a specific element based on a 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
Enter fullscreen mode Exit fullscreen mode

[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
Enter fullscreen mode Exit fullscreen mode

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

findIndex() provide a 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
Enter fullscreen mode Exit fullscreen mode

  • [5] JavaScript delete operator- delete operator remove the element from the array but it creates an 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
Enter fullscreen mode Exit fullscreen mode

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 of using the 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.
Enter fullscreen mode Exit fullscreen mode

Conclusion:

  • Array pop(), shift(), splice(), and delete operator mutates the original array.
  • Array filter() follows the immutability pattern.

So, there is also the argument of mutability vs immutability. There are cases where the immutability pattern is best like when passing the array as props to other components or storing values in a redux store. But that doesn't mean mutation is bad. I often use splice() with findIndex() to delete an element because the use-case is like that. Consider the example below:

const myFunc = (id) => {
  let arr = [1,2,3,4];
  if(id >= 5) {
    arr.push(5) 
  } 
  return arr;
}
Enter fullscreen mode Exit fullscreen mode

So if you know what the code is really doing you can use any pattern.

Thanks for reading!
Any feedback is welcome. Twitter

Discussion (27)

pic
Editor guide
Collapse
lukeshiru profile image
△ LUKE知る

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]
Collapse
ortonomy profile image
🅖🅡🅔🅖🅞🅡🅨 🅞🅡🅣🅞🅝

Hmmm, splice is fine...

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

Concise, easy to understand, immutable.

Collapse
lukeshiru profile image
△ LUKE知る • Edited

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.
Thread Thread
ortonomy profile image
🅖🅡🅔🅖🅞🅡🅨 🅞🅡🅣🅞🅝 • Edited

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)

Thread Thread
lukeshiru profile image
△ LUKE知る • Edited

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.

Thread Thread
ortonomy profile image
🅖🅡🅔🅖🅞🅡🅨 🅞🅡🅣🅞🅝

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.

Collapse
maixuanhan profile image
Han Mai

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

Collapse
lukeshiru profile image
△ LUKE知る

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.

Thread Thread
maixuanhan profile image
Han Mai

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.

Thread Thread
lukeshiru profile image
△ LUKE知る

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.

Thread Thread
maixuanhan profile image
Han Mai • Edited

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.

Thread Thread
lukeshiru profile image
△ LUKE知る • Edited

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.

Thread Thread
maixuanhan profile image
Han Mai

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?

Thread Thread
lukeshiru profile image
△ LUKE知る

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.

Thread Thread
maixuanhan profile image
Han Mai

Time consuming, bye

Collapse
ip127001 profile image
Rohit Kumawat Author

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().

Collapse
lukeshiru profile image
△ LUKE知る

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".

Thread Thread
ip127001 profile image
Rohit Kumawat Author

I will surely check it out!

Collapse
perpetualwar profile image
Srđan Međo

Splice has its place, same as immutable approaches.

Collapse
lukeshiru profile image
△ LUKE知る

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).

Collapse
bhagatparwinder profile image
Parwinder 👨🏻‍💻

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];
Enter fullscreen mode Exit fullscreen mode

Poof! The last three elements are gone.

Collapse
ip127001 profile image
Rohit Kumawat Author

Thanks for reading and a great suggestion!

Collapse
calvintwr profile image
calvintwr

This indeed is the fastest! 😂

Collapse
calvintwr profile image
calvintwr • Edited

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.

Collapse
ip127001 profile image
Rohit Kumawat Author

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

Collapse
dillondizagoeda profile image
Dillon Goeda

[3.2] With findIndex() method

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

Collapse
ip127001 profile image
Rohit Kumawat Author

Thanks for reading the article and pointing out the mistake.