Семейство методов 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
, чтобы сравнить значения, чтобы определить, являются ли элементы уникальными.