Хранение уникальных значений в JavaScript

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

Для таких задач удобно использовать Set. Он хранит только уникальные значения и не добавляет элемент повторно, если такой уже есть.

Создание коллекции

Пустую коллекцию можно создать с помощью new Set().

let selectedTags = new Set()

Если начальные значения уже есть, их можно передать массивом.

let selectedTags = new Set(['javascript', 'html', 'css'])

Добавление значений

Для добавления элемента используется метод add().

let selectedTags = new Set()

selectedTags.add('javascript')
selectedTags.add('html')
selectedTags.add('javascript')

console.log(selectedTags) // Set(2) {'javascript', 'html'}

Значение ‘javascript’ добавили два раза, но в коллекции оно осталось один раз.

Проверка наличия значения

Перед добавлением или выполнением действия можно проверить, есть ли значение в коллекции. Для этого используется метод has().

let viewedLessons = new Set([101, 102, 103])

viewedLessons.has(102) // true
viewedLessons.has(200) // false

Такая проверка удобна, когда нужно понять, выполнялось ли действие раньше.

let sentMessages = new Set()

function sendMessage(id) {
  if (sentMessages.has(id)) {
    return
  }

  sentMessages.add(id)

  console.log(`Сообщение ${id} отправлено`)
}

sendMessage(1) // Сообщение 1 отправлено
sendMessage(1) // повторной отправки не будет

Удаление значений

Если значение больше не нужно хранить, его можно удалить методом delete().

let selectedIds = new Set([1, 2, 3])

selectedIds.delete(2)

console.log(selectedIds) // Set(2) {1, 3}

Метод возвращает true, если значение было найдено и удалено, и false, если такого значения не было.

selectedIds.delete(3) // true
selectedIds.delete(10) // false

Количество уникальных значений

Количество элементов хранится в свойстве size.

let selectedTags = new Set(['javascript', 'html', 'css'])

selectedTags.size // 3

Это удобно для счетчиков: сколько тегов выбрано, сколько id уже обработано, сколько уникальных значений встретилось.

Преобразование в массив

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

let selectedTags = new Set(['javascript', 'html', 'css'])

let tagsArray = Array.from(selectedTags)

console.log(tagsArray) // ['javascript', 'html', 'css']

Можно использовать и spread-оператор.

let tagsArray = [...selectedTags]

После этого доступны обычные методы массивов: map(), filter(), join() и другие.

Уникальные объекты

С объектами Set работает по ссылке. Если два объекта выглядят одинаково, но созданы отдельно, для JavaScript это разные значения.

let firstUser = { id: 1 }
let secondUser = { id: 1 }

let users = new Set()

users.add(firstUser)
users.add(secondUser)

users.size // 2

Если нужно хранить уникальных пользователей по id, проще хранить сами id.

let userIds = new Set()

userIds.add(1)
userIds.add(1)

userIds.size // 1

Когда использовать Set

Set хорошо подходит, когда нужно хранить набор уникальных значений и часто проверять, есть ли значение в наборе.

  • id выбранных элементов;
  • список уникальных тегов;
  • посещенные страницы или уроки;
  • значения, которые уже были обработаны.

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

Итого

Set помогает хранить уникальные значения без дополнительных проверок на дубли. В него можно добавлять элементы, проверять наличие, удалять значения и быстро узнавать размер коллекции. Для простых значений это самый удобный вариант, если повторения не нужны.