Семейство методов Lodash 'uniq' без проблем может быть реализовано на простом JS.

Lodash - очень полезная служебная библиотека, которая позволяет нам легко работать с объектами и массивами.
Однако теперь, когда стандартная библиотека JavaScript догоняет такие библиотеки, как Lodash, мы можем реализовать многие функции простыми способами.
В этой статье мы рассмотрим и узнаем больше о JavaScript, реализовав некоторые методы Lodash на простом JavaScript, включая uniq uniqBy и uniqWith.
«Uniq»
Метод Lodash uniq создает массив без повторяющихся значений. В возвращаемом массиве появляется только первое вхождение каждого значения.
Поскольку в JavaScript уже есть структура данных set, мы можем использовать ее с оператором распространения, чтобы удалить все дубликаты из исходного массива и вернуть его.
Мы можем реализовать это следующим образом:
const uniq = arr => [...new Set(arr)]
В приведенном выше коде мы просто преобразовали arr в набор для удаления повторяющихся значений, а затем преобразовали его обратно в массив с помощью оператора распространения.
Затем, когда мы назовем это следующим образом ...
const result = uniq([1, 2, 2, 3]);
… Мы получаем, что result это [1, 2 ,3].
'uniqBy'
uniqBy похож на uniq, за исключением того, что он принимает функцию iteratee, которая запускается перед сравнением значений на предмет уникальности. Это означает, что мы не можем просто преобразовать его в набор. Вместо этого мы должны запустить iteratee, а затем сравнить их с существующими записями в возвращаемом массиве.
Для этого мы реализуем uniqBy следующим образом:
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;
}
В приведенном выше коде у нас есть массив uniques, который будет содержать массив уникальных записей, которые мы вернем.
Затем мы перебираем arr с помощью цикла for...of. Внутри цикла мы сопоставляем массив uniques с iteratee, чтобы получить сопоставленные значения.
Затем мы проверяем, есть ли каждая запись массива уже в uniques, проверяя, находится ли она в массиве mappedUniques вместо uniques, поскольку мы хотим сравнить уникальность после того, как она была преобразована функцией iteratee.
Если он не включен проверкой методом includes, мы помещаем значение в uniques.
По завершении цикла мы возвращаем uniques. Затем, когда мы назовем это следующим образом:
const result = uniqBy([1, 2, 2.1, 3], Math.floor);
Тогда result равно [1, 2, 3], поскольку 2 и 2.1 совпадают после вызова Math.floor на них. iteratee может быть любой функцией, которая принимает один аргумент и возвращает что-то производное от него.
'uniqWith'
uniqWith похож на uniq, за исключением того, что он принимает компаратор, который запускается для сравнения существующих значений, которые имеют уникальные значения, с теми, которые не имеют.
Если записи в исходном массиве нет в массиве с уникальными значениями, мы помещаем ее в массив с уникальными значениями.
Массив с уникальными значениями возвращается в конце после проверки всех значений в данном массиве.
Мы можем реализовать это следующим образом:
const uniqWith = (arr, comparator) => {
let uniques = [];
for (let a of arr) {
if (uniques.findIndex(u => comparator(a, u)) === -1) {
uniques.push(a);
}
}
return uniques;
}
В приведенном выше коде мы имеем:
uniques.findIndex(u => comparator(a, u)) === -1
Это проверяет, совпадают ли элементы в uniques с записью массива, который мы просматриваем в цикле. Если это не так (на что указывает возвращаемое значение -1), мы помещаем его в uniques.
Когда цикл завершен, мы возвращаем uniques.
Затем запускаем его следующим образом:
const result = uniqWith([1, 2, 2.1, 3], (a, b) => Math.floor(a) === Math.floor(b));
Отсюда мы получаем [1, 2, 3] как значение result, поскольку наш компаратор определяет, что если нижний предел обоих значений одинаков, то они одинаковы. Функция comparator должна принимать два аргумента с двумя значениями для сравнения.
Заключение
Метод uniq Lodash можно легко реализовать с помощью простых наборов JavaScript и оператора распространения.
uniqBy немного сложнее реализовать, поскольку нам нужно сопоставить значения с переданной функцией iteratee, прежде чем мы сможем сравнить их на уникальность.
uniqWith похож на uniqBy в том, что мы должны запустить функцию comparator, чтобы сравнить значения, чтобы определить, являются ли элементы уникальными.