Что делает функция uniq для удаления повторяющихся значений из массива?
Что проверяют
Знаете ли вы, как в JavaScript сравниваются значения при удалении дубликатов, и оцениваете ли сложность своего решения. Задача звучит как разминка, но её обычно дают, чтобы дальше поговорить про Set, ссылки и производительность.
Как отвечать
Для примитивов короткий ответ такой:
const uniq = (arr) => [...new Set(arr)];Set хранит значения по правилу SameValueZero, порядок вставки сохраняется, проход линейный. Наивный вариант с includes или indexOf внутри цикла даёт квадратичную сложность: на десятке элементов это незаметно, на десятках тысяч уже нет.
Про сравнение стоит сказать отдельно:
- объекты и массивы сравниваются по ссылке, поэтому два одинаковых по содержимому объекта останутся оба;
NaNравен сам себе вSetи вincludes, но не вindexOf, поэтому приёмarr.filter((v, i) => arr.indexOf(v) === i)теряет такие значения;- нуль со знаком схлопывается в одно значение.
Дедупликация объектов по ключу делается через Map:
const uniqBy = (arr, key) =>
[...new Map(arr.map((item) => [item[key], item])).values()];Здесь побеждает последний встреченный элемент. Если нужен первый, ключ добавляют только когда его ещё нет.
Где спотыкаются
Показывают цикл с includes и называют его оптимальным. На собеседовании ждут именно оценки: два прохода по массиву внутри друг друга это квадрат, и объяснить это важнее, чем вспомнить синтаксис.
Второе: пробуют снять дубликаты объектов через Set и удивляются, что ничего не удалилось. Следующий шаг обычно JSON.stringify как ключ, но он зависит от порядка полей и ломается на вложенных структурах и на значениях, которые не сериализуются.
Третье: сортируют массив ради соседних дубликатов. Сортировка меняет исходный массив на месте и теряет исходный порядок, а для строк ещё и сравнивает не так, как ожидает пользователь.