JavaScript array methods 1/3 - altering arrays

danieo

Daniel BudziΕ„ski

Posted on August 15, 2021

JavaScript array methods 1/3 - altering arrays

The Array prototype in modern JavaScript contains many useful methods which every developer should know. However, some of them were introduced in the more recent ECMAScript. So if you don't keep up with the newest standards or you're just a beginner - it is a good time to learn something new. I'm also going to show you some tricks and trivia about these methods.


Before you read

If you're an absolute beginner before reading this article you can check my brief introduction to JavaScript arrays where I discussed this construct in short.

How to add new items to an array?

push()! One of the most common operations that we can do on arrays. It simply adds new elements to the array.

const array = ["πŸ’", "🐬", "πŸ…"];
array.push("πŸ“");
console.dir(array) // Output: ["πŸ’", "🐬", "πŸ…", "πŸ“"]
Enter fullscreen mode Exit fullscreen mode

push() will automatically extend the size of the array and add our new element at the end. We can push() more than one element at once:

const array = ["πŸ’", "🐬", "πŸ…"];
array.push("πŸ“", "πŸ‰", "πŸ„");
console.dir(array) // Output: ["πŸ’", "🐬", "πŸ…", "πŸ“", "πŸ‰", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

It's also worth noting that push() returns the new length of the array.

const array = ["πŸ’", "🐬", "πŸ…"];
console.dir(array.push("πŸ‰")); // Output: 4
console.dir(array); // Output: ["πŸ’", "🐬", "πŸ…", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Sometimes we may need to manually extend an array and add elements at certain indexes.

const array = [];
array[2] = "🐬";
console.dir(array); // Output: [undefined, undefined, "🐬"]
array[0] = "πŸ…";
array[1] = "πŸ‰";
console.dir(array); // Output: ["πŸ…", "πŸ‰", "🐬"]
Enter fullscreen mode Exit fullscreen mode

In this example, we create an empty array. The next line extends its size to n+1 and adds 🐬 as the last value.

Thanks to the console.dir() in the third line you can see that there are some undefined values in this array. As I said in my brief introduction to JavaScript arrays, when you're extending the length of an array, JavaScript creates new elements with undefined values to meet the new size.

This method also works on existing arrays:

const array = ["πŸ…", "🐬"];
array[4] = "πŸ„";
console.dir(array); // Output: ["πŸ…", "🐬", undefined, undefined, "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

How to concat/merge arrays?

One of the possibilities is to use concat():

const array1 = ["πŸ’", "🐬", "πŸ…"];
const array2 = ["πŸ“", "πŸ‰"];
const result = array1.concat(array2);
console.dir(result); // Output: ["πŸ’", "🐬", "πŸ…", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

It merges two or more arrays and returns the new array. Here's an example on three arrays:

const array1 = ["πŸ’", "🐬", "πŸ…"];
const array2 = ["πŸ“", "πŸ‰"];
const array3 = ["🐎", "πŸ„"];
const result  = array1.concat(array2, array3);
console.dir(result); // Output: ["πŸ’", "🐬", "πŸ…", "πŸ“", "πŸ‰", "🐎", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

But what if I want to merge one array INTO another array without the need to assign a third variable? ES2015 introduced a so-called destructuring assignment which in combination with push() can do it!

const array1 = ["πŸ’", "🐬", "πŸ…"];
const array2 = ["πŸ“", "πŸ‰"];
array1.push(...array2);
console.dir(array1); // Output: ["πŸ’", "🐬", "πŸ…", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Ta dam! Now we have all of the elements of the second array in our first array.

Using destructuring we can achieve a similar behavior to concat(). We just need to destruct the merged arrays into another array.

const array1 = ["πŸ’", "🐬", "πŸ…"];
const array2 = ["πŸ“", "πŸ‰"];
const array3 = ["🐎", "πŸ„"];
const result = [...array1, ...array2, ...array3];
console.dir(result);
Enter fullscreen mode Exit fullscreen mode

Removing elements from the array

How to remove the last element from the array?

It's as simple as calling the pop() function on the array.

const array = ["πŸ…", "🐬", "πŸ„"];
array.pop();
console.dir(array); // Output: ["πŸ…", "🐬"]
Enter fullscreen mode Exit fullscreen mode

pop() has also a useful property because it returns the removed element!

const array = ["πŸ…", "🐬", "πŸ„"];
const lastElement = array.pop();
console.dir(lastElement); // Output: "πŸ„"
Enter fullscreen mode Exit fullscreen mode

How to remove the first element from the array?

Here in handy comes shift(). Similar to pop() it also returns the element being removed.

const array = ["πŸ…", "🐬", "πŸ„"];
const firstElement = array.shift();
console.dir(firstElement); // Output: "πŸ…"
console.dir(array); // Output: ["🐬", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

How to remove elements from the array on a specific index?

To remove a specific element we can use the delete operator.

const array = ["πŸ…", "🐬", "πŸ„"];
delete array[1];
console.dir(array); // Output: ["πŸ…", undefined, "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

It removes the element completely - the array now does not have an element with index 1. The interesting part of this is the fact, that we are still left with an array with a length of 3. If you want to leave the element and don't want it to have value just set it to undefined. Example:

const array = ["πŸ…", "🐬", "πŸ„"];
delete array[1];
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: false
console.dir(array); // Output: ["πŸ…", undefined, "πŸ„"]

array[1] = '🐬';
array[1] = undefined;
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["πŸ…", undefined, "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

But what when we want to remove the element AND shorten the array? For this case, we can use splice().

const array = ["πŸ…", "🐬", "πŸ„"];
array.splice(1, 1);
console.dir(array); // Output: ["πŸ…", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

The first argument of splice() is the startIndex, it sets the place where we want to start "cutting" our array. The second argument determines the length of the "cut". In 0ut case we only want to delete "🐬" so we just start "cutting" on index 1 and we want to remove just one element. Here is another example of removing more elements.

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
array.splice(2, 3);
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Now our "cut" has started on "πŸ„" and we wanted to remove three elements starting from that place.

With splice, we can also fill the gap of the removed elements by passing more arguments.

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
array.splice(2, 2, "πŸ–", "πŸ¦™");
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ–", "πŸ¦™", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

or using destructuring, we can fill the gap with another array.

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
const fillArray = ["πŸ–", "πŸ¦™"];
array.splice(2, 2, ...fillArray);
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ–", "πŸ¦™", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Now let's compare all three methods and see the results!

const array = ["πŸ…", "🐬", "πŸ„"];
delete array[1];
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: false
console.dir(array); // Output: ["πŸ…", undefined, "πŸ„"]

array[1] = "🐬";
array[1] = undefined;
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["πŸ…", undefined, "πŸ„"]

array[1] = "🐬";
array.splice(1,1);
console.dir(array.length); // Output: 2
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["πŸ…", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

Reassuming:

  • delete removes the element but does not affect the array's size.
  • setting an element to undefined does not remove it completely nor affects the array's size.
  • splice() removes the element and affects the array's size.

Creating a string from an array - joining all elements into one string

Sometimes we need to create one string from all of the elements of the array, we can do it by using join().

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
const result = array.join();
console.dir(result); // Output: "πŸ…,🐬,πŸ„,πŸ’,πŸ“,πŸ‰"
Enter fullscreen mode Exit fullscreen mode

We can also specify the separator by passing it as the first argument.

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
const result = array.join(' | ');
console.dir(result); // Output: "πŸ… | 🐬 | πŸ„ | πŸ’ | πŸ“ | πŸ‰"
Enter fullscreen mode Exit fullscreen mode

Creating an array from a string - splitting strings

We can achieve this by calling split() on our string. I know that split() is not a part of the Array prototype, but I thought that I should mention it when I'm talking about its counterpart - join().

const string = "πŸ…,🐬,πŸ„,πŸ’,πŸ“,πŸ‰";
const result = string.split();
console.dir(result); // Output: ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

The default separator for split() is "," but we can change it to whatever we want.

const string = "πŸ…|🐬|πŸ„|πŸ’|πŸ“|πŸ‰";
const result = string.split("|");
console.dir(result); // Output: ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

How to reverse an array?

JavaScript also has a method for this - and (how surprising...) it's named... reverse().

const array = ["πŸ…", "🐬", "πŸ„"];
const result = array.reverse();
console.dir(result); // Output: ["πŸ„", "🐬", "πŸ…"]
Enter fullscreen mode Exit fullscreen mode

But there is one problem with this method. It's mutating our original array. Well, it is only a problem if you want to preserve the original array.

const array = ["πŸ…", "🐬", "πŸ„"];
const result = array.reverse();
console.dir(result); // Output: ["πŸ„", "🐬", "πŸ…"]
console.dir(array); // Output: ["πŸ„", "🐬", "πŸ…"]
Enter fullscreen mode Exit fullscreen mode

What can we do to solve this issue? Well... just call concat() or slice() without any arguments.

const array = ["πŸ…", "🐬", "πŸ„"];
const result = array.concat().reverse();
console.dir(result); // Output: ["πŸ„", "🐬", "πŸ…"]
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

NOTE. This works because concat() and slice() are returning a copy of the array - not a reference. By using reverse() after them we're only altering the copy.

Or (a cleaner solution) using our best friend, the hero we all needed but didn't deserve him, destructuring assignment.

const array = ["πŸ…", "🐬", "πŸ„"];
const result = [...array].reverse();
console.dir(result); // Output: ["πŸ„", "🐬", "πŸ…"]
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

NOTE. Here we are just destructuring our array into another array, which is going to be reversed. So it's basically also calling reverse() on a copy.

We can also implement our own reverse function (this is only for absolute geeks).

Just kidding, we're not going to reinvent the wheel. I mean, you can, but... I'm too busy and we have to cover some more methods. However, these guys have time to do this, and you can check their thread for some funky solutions.

How to add new elements to the beginning of an array?

If JavaScript methods were people, push() and shift() would be a couple with a kid named unshift(). unshift() like push() will add new elements to the array but at the beginning.

const array = ["πŸ…", "🐬", "πŸ„"];
array.unshift("πŸ‰", "πŸ“");
console.dir(array); // Output: ["πŸ‰", "πŸ“", "πŸ…", "🐬", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

And like push() it also accepts more than one element.

const array1 = ["πŸ…", "🐬", "πŸ„"];
const array2 = ["🐎", "πŸ„"];
array1.unshift(...array1);
console.dir(array1); // Output: ["πŸ‰", "πŸ“", "πŸ…", "🐬", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

Also, we can use destructuring to merge an array to the beginning of another.

Also similarly to push(), unshift() returns the new length of the array.

const array = ["πŸ’", "🐬", "πŸ…"];
console.dir(array.unshift("πŸ“")); // Output: 4
console.dir(array); // Output: ["πŸ“", "πŸ’", "🐬", "πŸ…"]
Enter fullscreen mode Exit fullscreen mode

How to sort an array in JavaScript?

Sorting in JS is achieved with the sort() method. It utilizes an in-place algorithm so it doesn't copy the array, it alters the original.

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
array.sort();
console.dir(array); // Output: ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"]
Enter fullscreen mode Exit fullscreen mode

If we want to keep the original we can do the same trick that we have done with reverse().

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
const result = array.slice().sort();
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"]
console.dir(result); // Output: ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"]
Enter fullscreen mode Exit fullscreen mode
const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
const result = [...array].sort();
console.dir(array); // Output: ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"]
console.dir(result); // Output: ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"]
Enter fullscreen mode Exit fullscreen mode

NOTE. Emojis are just unicode characters and every emoji has it's unique code. For example πŸ„ is U+1F404 and πŸ‰ is U+1F409. The algorithm is going to sort by this codes.

By default, this method sorts the elements using an ascending order - from lower to higher. If we want to sort in descending order we can write our own compare function (more on that in a moment) or just reverse() the sorted array (as it's more performant).

const array = ["πŸ…", "🐬", "πŸ„", "πŸ’", "πŸ“", "πŸ‰"];
array.sort().reverse();
console.dir(array); // Output: ["🐬", "πŸ“", "πŸ’", "πŸ‰", "πŸ…", "πŸ„"]
Enter fullscreen mode Exit fullscreen mode

The default behavior of the sort() method causes also a very interesting problem, let's try to sort an array consisting of only numbers.

const array = [3, 45, 12, 1, 78, 369];
array.sort();
console.dir(array); // Output: [1, 12, 3, 369, 45, 78]
Enter fullscreen mode Exit fullscreen mode

It provides us with one conclusion.
Cat standing in snow, wondering how were these numbers sorted

This is because by default sort is converting the elements to strings and comparing them in UTF-16. So when comparing words like "water" and "fire", "fire" comes first but when converting numbers to strings like 100 and 5 we end up with "100" coming before "5". To solve this we need to provide our own compare function as the first argument.

const array = [3, 45, 12, 1, 78, 369];
array.sort((first, second) => first - second);
console.dir(array); // Output: [1, 3, 12, 45, 78, 369]
Enter fullscreen mode Exit fullscreen mode

Ah, much better.

NOTE. We use first - second rather than first > second because it's more performant.

Benchmark result - sort using arithmetics is faster than sort using comparison

The problem with sorting number arrays is not our only concern. If you're French, Polish, German, Czech, Spanish or a citizen of another country whose native language has some letters with diacritics and you want to compare some local strings... well your life is not easy then. Here's hows sort() is working with accent letters.

const array = ["turkuć podjadek", "konik polny", "komar", "mucha", "ćma"];
array.sort();
console.dir(array); // Output: ["komar", "konik polny", "mucha", "turkuć podjadek", "ćma"]
Enter fullscreen mode Exit fullscreen mode

This example is using some Polish insect names. The words with an accent are just put at the end. For example "Δ‡ma" should be first but it's last. To fix this we need to provide our own compare function again.

const array = ["turkuć podjadek", "konik polny", "komar", "mucha", "ćma"];
array.sort((first, second) => first.localeCompare(second));
console.dir(array); // Output: ["ćma", "komar", "konik polny", "mucha", "turkuć podjadek"]
Enter fullscreen mode Exit fullscreen mode

Now it's working. localeCompare() checks if the reference string comes after or before the string given.

How to get first/last/any n elements from an array?

slice() is the solution you're looking for. It accepts two arguments, the start index and the end index, both are optional, but when we provide neither of them - nothing happens. Here are some useful snippets.

Get the first 3 elements of an array

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(0, 3);
console.dir(result); // Output: ["πŸ„", "πŸ…", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Get the last element of an array

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(-1);
console.dir(result); // Output: ["🐬"]
Enter fullscreen mode Exit fullscreen mode

Get the second half of an array

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(array.length / 2);
console.dir(result); // Output: ["πŸ’", "πŸ“", "🐬"]
Enter fullscreen mode Exit fullscreen mode

Get the first half of an array

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(0, array.length / 2);
console.dir(result); // Output: ["πŸ„", "πŸ…", "πŸ‰"]
Enter fullscreen mode Exit fullscreen mode

Get elements after the fourth element

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(4);
console.dir(result); // Output: ["πŸ“", "🐬"]
Enter fullscreen mode Exit fullscreen mode

Get a slice of the array

const array = ["πŸ„", "πŸ…", "πŸ‰", "πŸ’", "πŸ“", "🐬"];
const result = array.slice(2, 4);
console.dir(result); // Output: ["πŸ‰", "πŸ’"]
Enter fullscreen mode Exit fullscreen mode

As you can see, slice() can do many things.

How to flatten arrays?

Flattening means reducing the dimensions of an array. For example, if we got a two-dimensional array we can reduce it to only one dimension using flat().

const array = [["πŸ“", "πŸ„"], ["πŸ…", "πŸ’"]];
const result = array.flat();
console.dir(result); // Output: ["πŸ“", "πŸ„", "πŸ…", "πŸ’"]
Enter fullscreen mode Exit fullscreen mode

Flattening doesn't affect the original array. It's copying its values.

By default flat() is going to flatten only one dimension. If you need to flatten a three (or more) dimensional array to just one dimension you have to provide the depth argument.

const array = [["πŸ“", "πŸ„"], ["πŸ…", ["πŸ’", "πŸ’"]]];
const result = array.flat(2);
console.dir(result); // Output: ["πŸ“", "πŸ„", "πŸ…", "πŸ’", "πŸ’"]
Enter fullscreen mode Exit fullscreen mode

How to copy elements within an array?

Sometimes you want to copy an element from one position to another. For this, you can use copyWithin(). Like slice() this method has many possible use cases.

Copy first two elements to the last two elements

const array = ["πŸ‰", "πŸ’", "πŸ“", "🐬", "πŸ„", "πŸ…"];
array.copyWithin(-2);
console.dir(array); // Output: ["πŸ‰", "πŸ’", "πŸ“", "🐬", "πŸ‰", "πŸ’"]
Enter fullscreen mode Exit fullscreen mode

Replacing one value with another

const array = ["πŸ‰", "πŸ’", "πŸ“", "🐬", "πŸ„", "πŸ…"];
array.copyWithin(2, 0, 1);
console.dir(array); // Output: ["πŸ‰", "πŸ’", "πŸ‰", "🐬", "πŸ„", "πŸ…"]
Enter fullscreen mode Exit fullscreen mode

Here we replaced the πŸ“ on index 2, with the piece that goes from index 0 to index 1, which is the πŸ‰. By changing the second argument to 2 we would also affect the 🐬, basically inserting the πŸ‰ and πŸ’ on the positions where πŸ“ and 🐬 were.

const array = ["πŸ‰", "πŸ’", "πŸ“", "🐬", "πŸ„", "πŸ…"];
array.copyWithin(2, 0, 2);
console.dir(array); // Output: ["πŸ‰", "πŸ’", "πŸ‰", "πŸ’", "πŸ„", "πŸ…"]
Enter fullscreen mode Exit fullscreen mode

For now - that's all. We've discussed all methods from the Array prototype that are used to alter arrays. This article series is going to be divided into 3 parts, the next part will deal with array iterators and looping through them, and the third would be about searching elements in arrays. If you appreciate my work consider visiting my blog and signing to my newsletter (I don't spam, you will be noticed only about my newest content :D).

πŸ’– πŸ’ͺ πŸ™… 🚩
danieo
Daniel BudziΕ„ski

Posted on August 15, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related