Merge Arrays in JavaScript: With and Without Duplicates
If you already understand the basics of JavaScript arrays, it's time to take your skills to the next level with more advanced topics. In this series of tutorials, you'll explore intermediate-level topics for programming with arrays in JavaScript.
In this post, you'll learn how to combine multiple arrays into a single array in JavaScript. This is known as merging arrays. This is a simple problem that has multiple solutions. I'll show you the most widely used and optimal ways of merging arrays.
The way you merge arrays depends on whether you want to remove duplicate values and whether you want to modify the original array or create a new array. We'll look at each kind in this post.
Method | Modifies Array? | Duplicates? | Time Complexity |
---|---|---|---|
[...] spread operator |
immutable | keeps duplicates | O(N) |
Array.concat() |
immutable | keeps duplicates | O(N) |
Array.push() |
modifies array | keeps duplicate | O(N) |
for loop | modifies array | removes duplicates | O(N2) |
filter and concat |
immutable | removes duplicates | O(N2) |
Set |
immutable | removes duplicates | O(N) |
Merge Arrays Allowing Duplicate Values
Spread Operator
One of the newest and most concise ways to perform an array merge is with the spread operator. The spread operator [...]
syntax allows two or more arrays to be adjoined. This will create a new array, without modifying the parent arrays.
1 |
const mergedArray = [...array1, array2] |
This method does not remove duplicates. Instead, all the array elements in the merged array will be inserted in the same order as the source. Here is an example to help you understand:
1 |
const array1 = [1,2,3] |
2 |
const array2 = [1,2,4] |
3 |
|
4 |
const merged = [...array1, array2] |
5 |
console.log(merged) // [1, 2, 3, 1, 2, 4] |
Time Complexity of the Spread Operator
The Spread operator makes use of [Symbol.iterator]
, which is a property of the object. In the case of merging two arrays, the spread operator iterates through each element in the array using the .next()
function. This results in a time complexity of O(N).
Array Concat
If you are searching for a functional method to merge arrays, Array.concat()
will be useful. Also, if you are unsure about the type of input, use Array.concat()
.
1 |
const mergedArray = array1.concat(array2) |
You can also use this syntax:
1 |
const mergedArray = [].concat(array1, array2) |
The concat
function is an immutable way of merging arrays. It does not modify the parent arrays, but creates a new merged array. The array items will be inserted in the same order as the source.
1 |
const array1 = [1,2,3] |
2 |
const array2 = [1,2,4] |
3 |
|
4 |
const merged = [].concat(array1, array2) |
5 |
or
|
6 |
const merged = array1.concat(array2) |
7 |
console.log(merged) // [1, 2, 3, 1, 2, 4] |
The concat
function allows you to merge two or more arrays.
1 |
const mergedArray = array1.concat(array2, array3, array4 .... arrayN); |
Time Complexity
The concat
function can have better performance than the spread operator. This is because concat
uses array-specific optimisation methods. On the other hand, the spread operator relies on the common iteration protocols. I tested some large arrays on different browsers to compare the spread operator and concat
:
Browser | Spread Operator | Concat |
---|---|---|
Chrome | 626.5ms | 230.1ms |
Firefox | 900.40ms | 820.20ms |
Edge | 1740.7ms | 700.3ms |
Safari | 165.3ms | 144.34ms |
concat
function is O(N).Array Push
If the array merge method should not create a new array, array.push
will be useful. This method allows you to merge an element into an existing array. The newly added element will be inserted at the end of the array. This makes array.push
a mutable way of merging.
1 |
const array1 = [1,2,3] |
2 |
array1.push(4) |
3 |
array2.push(2) |
4 |
console.log(array1) // [1, 2, 3, 4, 2] |
You can push an array into an existing array using the spread operator.
1 |
const array1 = [1,2,3] |
2 |
const array2 = [1,2,4] |
3 |
array1.push(...array2) |
4 |
|
5 |
console.log(array1) // [1, 2, 3, 1, 2, 4] |
When you want to merge two or more arrays using array.push()
, you can use the following syntax:
1 |
const array1 = [1,2,3]; |
2 |
const array2 = [4,5,6]; |
3 |
const array3 = [7,8,9]; |
4 |
|
5 |
array1.push(...[...array2, ...array3]); // [1,2,3,4,5,6,7,8,9] |
Time Complexity
The array push operation costs O(1) for a single element. If you want to merge N elements, it will cost O(N). During the array merge, a copy cost of O(N) will be incurred when an array slot is allocated and a new item is inserted.
Array.push
is O(N).Merging Arrays and Removing Duplicate Values
The Traditional For Loop
The traditional method for merging two arrays involves two or more for-loops based on the number of arrays.
Algorithm
- Iterate through each item of the new array.
- Use
indexOf()
to judge whether that item is already present in the old array. - If it is not present, add it to the old array.
1 |
function merge(array1, array2) { |
2 |
for (let i=0; i<array2.length; i++) |
3 |
if (array1.indexOf(array2[i])==-1) |
4 |
array1.push(array2[i]); |
5 |
|
6 |
return array1; |
7 |
}
|
Time Complexity
For merging two same-sized arrays using this algorithm, the indexOf
method needs to be called for each of the N elements of the new array. And each call to indexOf
takes O(N) time to search through the old array. So the overall time complexity is O(N2).
Filter and Concat With ES5
This solution replaces the for loops with the built-in array functions concat
and filter
.
concat()
can be used to merge multiple arrays together, but it does not remove duplicates.
filter()
is used to remove duplicates from the merged array. Just like the traditional for loop, filter uses the indexOf()
method to judge the occurrence of an item in the merged array.
Algorithm
- concat() the arrays together, and store them in another array.
- Use the filter() to iterate through the merged array and remove any item that occurs multiple times.
1 |
function merge(array1, array2) { |
2 |
let arrayMerge = array1.concat(array2) |
3 |
return arrayMerge.filter( (item, index) => |
4 |
arrayMerge.indexOf(item) == index |
5 |
)
|
6 |
}
|
Time Complexity
For merging two same-sized arrays with this algorithm, the concat takes O(N) time. Then the filter calls indexOf
on each element of the resulting array, again with O(N2) time.
filter
and concat
solution is O(N2).Merging Arrays With a Set
ES6 offers a single-line solution for merging arrays without duplicates. It uses the spread operator and a Set.
Set
is a built-in data structure in JavaScript ES6 and above that does not support duplicates. This is where concat()
and Set
deviate—Set
checks for duplicates and removes them. So much of our job is done by the data structure.
Code for Merging Arrays With a Set
- Collect the unique values for the two arrays in a
Set
. - Use the spread operator to convert the
Set
back to an array.
1 |
function merge(array1, array2) { |
2 |
return [... new Set[...array1, ...array2])]; |
3 |
}
|
Time Complexity
Set
, the time complexity is O(N).Conclusion
In this tutorial, we have seen several different ways of merging two arrays in JavaScript. If you are ready to merge with duplicates, the most optimal solutions include concat
and the spread operator.
We also saw how to remove duplicates from merged arrays. The solution offered by ES6 is the simplest and the least expensive. With a time complexity of O(N), this is the ideal choice for merging two or more arrays while removing duplicates.
Method | Modifies Array? | Duplicates? | Time Complexity |
---|---|---|---|
[...] spread operator |
immutable | keeps duplicates | O(N) |
Array.concat() |
immutable | keeps duplicates | O(N) |
Array.push() |
modifies array | keeps duplicate | O(N) |
for loop | modifies array | removes duplicates | O(N2) |
filter and concat |
immutable | removes duplicates | O(N2) |
Set |
immutable | removes duplicates | O(N) |