JavaScript: Combine Two Arrays and Return Unique Values
As a JavaScript developer, it’s pretty common to be asked — whether in an interview question or in an effort to manage data — to merge two or more arrays and remove all duplicates, returning only the unique values. The process is often referred to as “de-duping,” and it’s part of your life if you’re a dev working with any sort of data.
As with everything in JavaScript, there are a few different ways to tackle this. I’m going to talk about two approaches:
- using the
spread
operator to merge andfilter()
andindexOf()
to remove duplicates; - the newer
Set
, which magically does both things at once.
Merge Arrays Using Spread Operator
Let’s start with these two arrays:
let myIceCream = ["chocolate", "vanilla", "pistachio"];
let yourIceCream = ["spumoni", "chocolate", "coconut"];
You can see that chocolate appears in both arrays, and in the next filter()
step we’ll figure out how to have only one chocolate ice cream(so sad). But for now, we’ll just merge these two arrays together.
I like using the spread
operator to merge because (if you want to) you’re able to preserve the two original arrays and get a whole new third array to manipulate as you like. Also, it’s easy — only one step!
let allIceCream = [...myIceCream, ...yourIceCream];
The spread
operator is saying, “Please spread out all of the elements in the myIceCream
array and put them together with all of the elements in the yourIceCream
array.”
Our new merged array looks like this:
allIceCream = ["chocolate", "vanilla", "pistachio", "spumoni", "chocolate", "coconut"];
So fast! So delicious! Double chocolate!
Remove Duplicates Using filter() and indexOf()
To iterate over these values and remove duplicates, let’s use the filter()
and indexOf()
methods. filter()
creates a new array from all values that pass the condition that we set, and it works for primitive types (like strings, which is what we have). indexOf()
returns the index of only the first occurrence of a specified item.
filter()
has a callback method that always takes the currentValue
parameter, but it also has an optional index
parameter, which is useful for comparing values in an array.
Just to show what we’re doing, here’s a quick reminder of the indexes of the items in the allIceCream
array:
allIceCream[0] = "chocolate"
allIceCream[1] = "vanilla"
allIceCream[2] = "pistachio"
allIceCream[3] = "spumoni"
allIceCream[4] = "chocolate"
allIceCream[5] = "coconut"
And now here’s the code for our filter()
method written in concise arrow function syntax:
allIceCream.filter((item, index) => allIceCream.indexOf(item) === index);
What’s happening here:
- we’re calling the
filter()
method on theallIceCream
array, and it checks every array element; - we pass in the parameters of
item
andindex
; item
looks at each current item, andindex
looks at its index;indexOf()
searches the array for eachitem
that is passed in (because we’re using filter, everyitem
is checked), and it returns only the first occurrence along with its array position;- the first occurrence of chocolate is at index[0] — the
indexOf()
thatitem
gets checked for strict equality against theindex
, and it matches, so it passes; - the second occurrence of chocolate is at index[4], but there’s already a chocolate at index[0];
- chocolate at index[4] doesn’t pass our condition and is discarded, so no duplicates end up in our final array!
Set
There’s an ES6 object called Set
that is even easier than the spread
/ filter()
/ indexOf()
system that I just showed. Check it out!
We’re starting with the same arrays as above:
let myIceCream = ["chocolate", "vanilla", "pistachio"];
let yourIceCream = ["spumoni", "chocolate", "coconut"];
and then we call the Set
object, using the square brackets to indicate that we’re spread
ing arrays and intend to evaluate them as whole arrays:
const allIceCream = new Set([
...myIceCream,
...yourIceCream
]);
The small catch is that you get an object back instead of an array, but that’s an easy fix:
const iceCreamArray = [...allIceCream];
and now we have this:
iceCreamArray = ["chocolate", "vanilla", "pistachio", "spumoni", "coconut"]
Only two steps! And such a small amount of code! And so readable!
Set
not only allows you to combine values, it also checks value equality (using the ===
strict equality operator) because each item in the set must be unique; the first instance of a value is preserved, and subsequent instances are discarded.