If you’ve been working with JavaScript for a while, then you’ve most likely encountered a situation where you needed to remove duplicate values from an array either gotten from an API response, generated by user input, or otherwise.
Scenario 1: Single Array Values
For example, if we wanted to remove duplicate values from an array-like:
const arr = [‘Jane’, ‘Raphael’, ‘Linda’, ‘Jane’, ‘Maggie’]
Prior to ES6, you would have written some long lines of code with a for-loop to achieve that. Now, thanks to the new Set data object, you can do that in just one line of code.
Set
only stores unique values, so when you pass in an array with duplicate values, it removes the duplicate.
To remove duplicate values, we’ll do:
const filteredArr = Array.from(new Set(arr));
In the code above, we create a new Set
object with the values of the arr array. Remember that Set
only accommodates unique values, so the duplicate values are removed. Next, we convert the Set
object back to an array, using the Array.from()
method.
Scenario 2: Array of Objects
For example, say you have the arr
array below, and we want to remove duplicate objects with the same name and status property.
const arr = [
{name: 'Jules', status: 'checked'},
{name: 'Linda', status:'pending'},
{name: 'Jules', status:'transit'},
{name: 'Linda', status:'pending'},
{name: 'Jules', status:'transit'}
]
Using Set
will not work in this case because it only works for arrays containing only primitive values.
In JavaScript, a primitive value is any value that is not an object. There are 7 primitive value types: string, number, bigint, boolean, undefined, symbol, and null.
This means that using the Set
method will not work for a typical array of objects. Not to worry, in such cases, we can whip up something with the Array.filter()
method.
To remove the duplicate values from the array of objects, we’ll do:
const names = arr.map(obj => obj.name);
const filteredArr = arr.filter((obj, index) => {
let foundIndex = names.indexOf(obj.name, index + 1);
return foundIndex === -1 ? true: !(JSON.stringify(obj) === JSON.stringify(arr[foundIndex]));
})
First, we’ll loop through the arr
array using the map
method to collect the values of a unique identifier into another array. In this case, the unique identifier for each object is the name
property.
Next, we use the filter method to loop through each object in the arr array. For every current object in iteration, we check if the value of its name property is present in the names array, starting from the next index. We do this, so we don’t have to loop through the entire array every time.
The indexOf method returns the position (i.e index) of the first occurrence of the value passed to it, within the provided array, starting from the index passed to it. If the value does not exist, it returns -1.
Lastly, we check if foundIndex
is equal to -1, if it is, we return true, which means that the current obj in iteration will be included in the filteredArr
. Else, we check if the current object is the same as the object at the position of the foundIndex
in the arr array. If it is, we negate the value to return false, which means that the current object in iteration will not be included in the filteredArr
.
In JavaScript, Objects are reference types, so you can’t just use ===
to compare two objects. That is why we use JSON.stringify
to convert the objects to strings and then compare them.
You should know, JSON.stringify
is a very hacky way to compare objects and is not very performance-friendly. For serious projects and large objects, please use the Lodash isEqual method.
Blog Credits: Linda Ikechukwu
Comments are closed.