Gernar
Frontend DeveloperJavaScript, алгоритмы и структуры данных

Интервью-вопрос

Как проверить, является ли массив уникальным

Для примитивов обычно достаточно сравнить размер Set с длиной массива. Главное на интервью: назвать это решение и не забыть ограничения для объектов, NaN и ручных проверок.

Добавлен
Редакция

Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.

🐰0
🥚0

Мини-квиз

Проверка перед разбором

Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.

Вопрос 1 из 50 правильно

Как лучше проверить уникальность массива строк?

Вы получили массив email-адресов. Все элементы уже строки.

Варианты ответа

Разбор

Разобраться, а не зазубрить

Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.

Базовая идея

Самый короткий ответ для интервью выглядит так:

const isUnique = (arr) => new Set(arr).size === arr.length;

Если в массиве был повтор, размер Set станет меньше длины массива. Если размеры равны, каждый элемент встретился один раз.

Такой ответ хорошо работает для примитивов: строк, чисел, boolean, null, undefined, symbol и bigint. Практический риск начинается там, где вы не уточнили тип элементов и критерий уникальности.

Что важно уточнить в ответе

Уникальность почти всегда зависит от смысла данных. Массив чисел уникален, если нет одинаковых чисел. Массив пользователей может быть уникален по id, по email или по паре полей. Это разные проверки.

Сильная формулировка:

Если это массив примитивов, я сравню размер Set с длиной массива. Если это массив объектов, сначала уточню критерий уникальности, например id, и буду проверять этот ключ.

Как выбрать подход

1В массиве только примитивы?
Используйте `new Set(arr).size === arr.length` или цикл с Set для раннего выхода.
2Нужно проверять объекты по конкретному полю?
Сравнивайте выбранный ключ, например `user.id`, а не весь объект.
3Ключ составной?
Соберите стабильный ключ из нормализованных частей, например `country + ':' + phone`.
4Проверка дорогая и идет в UI?
Считайте результат при изменении данных или мемоизируйте его. Не запускайте проверку без причины на каждом рендере.

Пример для объектов

Плохой вариант, если вам нужна уникальность пользователей по id:

const users = [{ id: 1 }, { id: 1 }];

const unique = new Set(users).size === users.length; // true

Этот код говорит, что массив уникален, потому что в нем две разные ссылки на объекты. Для UI это может привести к дублирующимся строкам в таблице, повторным опциям в селекте или неверной валидации формы.

Безопаснее проверять выбранный ключ:

const isUniqueBy = (items, getKey) => {
  const seen = new Set();

  for (const item of items) {
    const key = getKey(item);

    if (seen.has(key)) {
      return false;
    }

    seen.add(key);
  }

  return true;
};

const usersAreUnique = isUniqueBy(users, (user) => user.id);

Здесь есть ранний выход. Как только найден дубликат, функция сразу возвращает false. Это полезно для больших списков и валидации, которая запускается часто.

Ловушки сравнения

Set использует алгоритм SameValueZero. Для собеседования достаточно помнить два практических следствия: NaN считается равным NaN, а +0 и -0 считаются одним значением.

new Set([NaN, NaN]).size; // 1
new Set([+0, -0]).size; // 1

Если вы пишете ручную проверку через ===, поведение с NaN может отличаться. Это важно для данных из формы, парсинга чисел или API.

Сильный ход ответа
  1. 1Назвать короткое решение через Set
  2. 2Уточнить, что это про примитивы
  3. 3Сказать про объекты по ссылке
  4. 4Предложить ключ или функцию сравнения
Опасный ход ответа
  1. 1Сказать, что Set решает все случаи
  2. 2Не упомянуть NaN и ссылки
  3. 3Использовать объект как словарь без оговорок
  4. 4Предложить JSON.stringify как универсальный способ

Практический вывод

На интервью не стоит останавливаться только на одной строке кода. Лучше дать короткое решение, затем сразу показать границы применимости.

Хороший ответ:

Для примитивов я проверю new Set(arr).size === arr.length. Это линейная проверка по времени и памяти. Если элементы являются объектами, Set сравнит ссылки, поэтому я выберу ключ уникальности, например id, и буду хранить в Set уже эти ключи.

Если проверка запускается во frontend на каждом вводе пользователя, подумайте о стоимости. Для маленьких массивов простая читаемая проверка нормальна. Для больших списков лучше остановка при первом дубликате, а в React не стоит пересчитывать тяжелую проверку на каждом рендере без изменения данных.

Не используйте проверку уникальности как способ молча "починить" данные от API. Если сервер вернул дубли, UI должен либо показать понятную ошибку, либо явно удалить повторы по согласованному ключу. Иначе пользователь может выбрать не тот элемент, увидеть неверное состояние или отправить лишний запрос.

Частые ошибки

Где обычно ошибаются

Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.

  1. 1

    Проверять объекты через Set как примитивы

    new Set(users).size сравнит ссылки на объекты, а не их поля. Два объекта с одинаковым id останутся разными значениями. Если бизнес-смысл в id, проверяйте именно id. Иначе в UI могут появиться дубли строк, опций или выбранных элементов.
  2. 2

    Использовать обычный объект как универсальный словарь

    Ключи обычного объекта приводятся к строкам, поэтому разные значения могут слиться в один ключ. Например, разные объекты превращаются в похожий строковый ключ. Для произвольных значений лучше использовать Map или Set, а для объектов заранее выбирать стабильный ключ.
  3. 3

    Забывать про NaN в ручной проверке

    Проверка через === не считает NaN равным самому себе. Если вы пишете вложенные циклы, два NaN могут ошибочно пройти как уникальные. Set этот случай обрабатывает безопаснее.
  4. 4

    Считать JSON.stringify глубоким сравнением

    JSON.stringify зависит от формы данных и не сохраняет часть значений, например undefined в объектах. Это может дать ложную уникальность или ложные дубликаты. Если нужна глубокая уникальность, лучше явно нормализовать данные или выбрать проверенную функцию сравнения.
  5. 5

    Лечить дубли в React индексом массива

    Если данные не уникальны, key={index} только маскирует проблему. При сортировке, фильтрации или удалении React может переиспользовать не тот DOM-узел. Пользователь увидит неверное состояние строки или инпута. Безопаснее убрать дубли на уровне данных и использовать стабильный ключ.

Follow-up

Что могут спросить дальше

Короткие ответы на вопросы, которыми проверяют понимание Set, сравнения значений и практических ограничений.

Живые ответы

Видео с похожим вопросом

Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.

Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.

Содержание