In this article, we’ll look at and learn more about JavaScript by implementing some Lodash methods in plain JavaScript, including uniq
uniqBy
, and uniqWith
.
‘uniq’
The Lodash uniq
method creates an array without duplicate values. Only the first occurrence of each value appears in the returned array.
Since JavaScript already has the set
data structure, we can use that with the spread operator to remove all the duplicates from the original array and return it.
We can implement this as follows:
const uniq = arr => [...new Set(arr)]
In the code above, we just converted arr
to a set to remove duplicate values and then converted it back to an array with the spread operator.
Then when we call it as follows …
const result = uniq([1, 2, 2, 3]);
… we get that result
is [1, 2 ,3]
.
'uniqBy'
uniqBy
is like uniq
except it takes an iteratee
function, which is run before comparing the values for uniqueness. This means we can’t just convert it to a set. Instead, we have to run iteratee
and then compare them to the existing entries in the array we return.
To do that, we implement the uniqBy
in the following way:
const uniqBy = (arr, iteratee) => {
let uniques = [];
for (let a of arr) {
const mappedUniques = uniques.map(iteratee);
if (!mappedUniques.includes(iteratee(a))) {
uniques.push(a);
}
}
return uniques;
}
In the code above, we have the uniques
array, which will have the array of unique entries that we’ll return.
Then we loop through arr
with the for...of
loop. Inside the loop, we map the uniques
array with iteratee
to get the mapped values.
Next, we check if each array entry is already in uniques
by checking if it’s in the mappedUniques
array instead of uniques
since we want to compare the uniqueness after it’s been converted by the iteratee
function.
If it’s not included by checking with the includes
method, then we push the value into uniques
.
Once the loop is finished, we return uniques
. Then when we call it as follows:
const result = uniqBy([1, 2, 2.1, 3], Math.floor);
Then result
is [1, 2, 3]
since 2
and 2.1
are the same after calling Math.floor
on them. iteratee
can be any function that takes one argument and returns something derived from it.
'uniqWith'
uniqWith
is like uniq
except it accepts a comparator that’s run to compare the existing values that have unique values with the ones that doesn’t.
If the entry in the original array isn’t in the array with unique values, then we put it into the array with the unique values.
The array with unique values is returned in the end after checking all the values in the given array.
We can implement it as follows:
const uniqWith = (arr, comparator) => {
let uniques = [];
for (let a of arr) {
if (uniques.findIndex(u => comparator(a, u)) === -1) {
uniques.push(a);
}
}
return uniques;
}
In the code above, we have:
uniques.findIndex(u => comparator(a, u)) === -1
This checks to see if the items in uniques
are the same as the array entry that we’re looping through. If it isn’t (as indicated by the return value -1
), then we put it in uniques
.
When the loop is done, we return uniques
.
Then we run it as follows:
const result = uniqWith([1, 2, 2.1, 3], (a, b) => Math.floor(a) === Math.floor(b));
From this, we get [1, 2, 3]
as the value of result
since our comparator determines that if the floor of both values is the same, then they’re the same. The comparator
function has to take two arguments with the two values to compare.
Conclusion
The uniq
Lodash method can easily be implemented with plain JavaScript sets and the spread operator
uniqBy
is a bit harder to implement since we need to map the values with the iteratee
function that’s passed in before we can compare them for uniqueness.
uniqWith
is similar to uniqBy
in that we have to run the comparator
function to compare the values to determine if the items are unique.