Какую структуру данных использовать для хранения уникальных подписчиков?
Что проверяют
Знаете ли вы Set и Map в JavaScript не на уровне «убирает дубли», а с их правилами сравнения и поведением во фреймворке. Следом обычно спрашивают, как хранить такое множество в состоянии React или Redux и что будет, если подписчик это объект.
Как отвечать
Базовый ответ: Set. Добавление, удаление и проверка has() в среднем за константу, дубли не записываются, порядок вставки сохраняется. На массиве с includes() каждая проверка линейна, и дедупликация большого списка становится квадратичной.
Дальше важные детали:
- что кладём:
Setсравнивает по алгоритму SameValueZero, для объектов это сравнение ссылок. Два объекта с одинаковымidбудут разными элементами, поэтому храните идентификаторы, а данные держите вMapс ключомid; - нормализация: email перед добавлением приводят к нижнему регистру и обрезают пробелы, иначе
User@mail.ruиuser@mail.ruстанут двумя подписчиками; - React:
useStateсравнивает по ссылке, мутацияset.add(id)рендер не вызовет. Обновляйте через новый экземпляр:setSubs(prev => new Set(prev).add(id)); - Redux:
Setне сериализуется, Redux Toolkit предупредит об этом в dev-режиме. Там принято нормализованное состояние из массиваidsи объектаentities, его генерируетcreateEntityAdapter; - сериализация:
JSON.stringify(new Set([1]))вернёт"{}", перед отправкой или записью вlocalStorageпревращайте множество в массив через[...set].
В современных браузерах у Set есть методы union, intersection, difference, удобные для сравнения двух списков подписчиков.
Главное ограничение: настоящую уникальность гарантирует сервер уникальным индексом в базе. На клиенте Set отвечает за состояние интерфейса, а миллион подписчиков в браузер не грузят, их листают постранично.
Где спотыкаются
Кладут в Set объекты, собранные из ответа API, и удивляются, что одинаковые подписчики не схлопнулись.
Мутируют множество в состоянии React и не понимают, почему интерфейс не обновился.
Сериализуют Set напрямую, получают пустой объект и теряют данные при сохранении.