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