Множества и принадлежность: внутри или нет
Множество хранит один факт о значении: внутри или нет. Ни порядка, ни дубликатов, ни количества — поэтому у new Set([1, 2, 2, 3]) размер 3, а дедупликация и есть семантика множества. Разбираем ∈ против ⊆, пустое множество, множества-правила и типы как множества значений.
Аналитическая панель показывала: на новый баннер кликнули 9 412 пользователей. Маркетинг ликовал — пока кто-то не открыл выгрузку и не увидел один и тот же id снова и снова: каждое обновление страницы дописывало в массив ещё одно событие клика. Честное число после дедупликации — 3 107. Исправление заняло одну строку — new Set(userIds).size — и стоит притормозить на том, почему эта строка всё чинит. Массив отвечает на много вопросов о своём содержимом: что пришло первым, что последним, сколько раз встретилось значение. Множество отвечает ровно на один: это значение внутри или нет. Отбрасывание порядка и количества — не ограничение множеств, а их должностная инструкция, и именно поэтому множество — правильный инструмент всякий раз, когда единственный важный вопрос — «видел ли я это раньше?».
После этого урока ты можешь определить множество перечислением или правилом, записать и прочитать ∈ и ∉, объяснить, почему порядок и дубликаты внутри множества не существуют, различить принадлежность элемента (∈) и подмножество (⊆), описать пустое множество ∅ и распознать типы как множества значений.
Множество — это коллекция, о которой для каждого значения существует ровно один факт: принадлежность. Значение либо является членом (его ещё называют элементом) множества, либо нет. Символ принадлежности — ∈: x ∈ A читается «x является элементом A», а x ∉ A — «x не является элементом A». Простейшая нотация — перечислить элементы в фигурных скобках: {1, 2, 3} — множество, элементами которого являются ровно 1, 2 и 3.
Поскольку принадлежность — единственный факт, который хранит множество, порядок, дубликаты и количество внутри него просто не существуют. {1, 2, 3} и {3, 1, 2} — одно и то же множество: оба отвечают «да» на одни и те же вопросы о принадлежности. {1, 1, 2, 3} — тоже то же самое множество: записать элемент дважды не добавляет ничего, у «внутри» нет регулятора громкости. Два множества равны, когда у них одни и те же элементы — и ничего больше.
const clicks = [42, 7, 42, 42, 7];
const unique = new Set(clicks);
unique.size; // 2 — элементы это 42 и 7, и больше ничего
unique.has(42); // true — 42 ∈ unique
unique.has(99); // false — 99 ∉ unique
unique.add(7); // добавление уже существующего элемента ничего не меняет
unique.size; // всё ещё 2
new Set([1, 2, 2, 3]).size; // 3 — дедупликация И ЕСТЬ семантика множестваМножество можно также задать правилом (задание множества условием). Нотация {x : x чётно} читается «множество всех x таких, что x чётно». Всё после двоеточия — предикат, условие, истинное или ложное для каждого кандидата. Это открывает дорогу бесконечным множествам: натуральные числа ℕ — 0, 1, 2, 3, … — нельзя перечислить, но каждый вопрос о принадлежности имеет определённый ответ. Большего множеству и не нужно.
const isEven = (n) => n % 2 === 0; // множество {x : x чётно} — как правило
isEven(10); // true → 10 ∈ множеству
isEven(7); // false → 7 ∉ множеству
[1, 2, 3, 4, 5, 6].filter(isEven); // [2, 4, 6]Принадлежность (∈) и подмножество (⊆) — разные заявления на разных уровнях. Принадлежность x ∈ A спрашивает об одном значении: есть ли x в составе A? Подмножество A ⊆ B спрашивает о двух множествах: всякий ли элемент A есть в B? Возьмём A = {1, 2}: значение 1 ∈ A истинно; множество {1} ⊆ A истинно; но {1} ∈ A ложно — элементы A — числа 1 и 2, а не множество {1}. Пустое множество ∅ (без элементов) является подмножеством каждого множества, но элементом почти никакого.
Пусть A = {1, 2, 3}. Оцените каждое заявление как истинное или ложное и объясните почему.
2 ∈ A— Истина. Число 2 есть в составе A.{2} ∈ A— Ложь. Элементы A — числа. Множество {2} никогда не клалось в состав.{2} ⊆ A— Истина. У {2} один элемент — число 2, которое есть в A.∅ ⊆ A— Истина. Нет ни одного элемента ∅, которого могло бы не хватать в A — тривиально условие подмножества выполнено.∅ ∈ A— Ложь. Пустое множество никогда не клалось в состав {1, 2, 3}.{∅}имеет размер 1. Это коробка, содержащая одну вещь — пустую коробку. Не пустое.
▸Почему это работает
Зачем структура, которая столько забывает? Затем, что забывание делает ответы каноничными. Существует ровно одно множество с элементами 7 и 42 — поэтому у вопроса «видел ли я это значение?» есть ровно один честный ответ, как бы данные ни поступали. Большинство багов с коллекциями — это вопрос к журналу, заданный как к списку состава (считаем клики вместо пользователей), или наоборот. Выбор структуры — это выбор вопроса, который вообще способен задать ваш код.
Входит ли 3 в {1, 2, 3}? Ответьте «да» или «нет».
Одно ли это множество: {1, 2, 3} и {3, 1, 2}? Ответьте «да» или «нет».
Верно ли: {1} ∈ {1, 2}? Ответьте «да» или «нет».
Верно ли: {1} ⊆ {1, 2}? Ответьте «да» или «нет».
Чему равно new Set([5, 3, 5, 3, 5]).size? Напишите число.
Пусть A = {1, 2, 3}. Какая пара заявлений ОБОИХ истинна?
Множество — структура, знающая об одном значении одно: внутри или нет. Принадлежность записывается x ∈ A; множество задаётся перечислением — {1, 2, 3} — или правилом вроде {x : x чётно}, где правило — предикат. Поскольку принадлежность — единственный хранимый факт, у множеств нет порядка, дубликатов и количества: {3, 1, 2} и {1, 1, 2, 3} — то же множество, что {1, 2, 3}, а размер 3 у new Set([1, 2, 2, 3]) — это определение за работой. Два заявления живут на разных уровнях: x ∈ A — об одном значении, A ⊆ B — о том, всякий ли элемент A есть в B. Одноэлементное {1} — подмножество {1, 2}, но не его элемент; ∅ — подмножество всего и элемент почти ничего, а {∅} — коробка с пустой коробкой внутри, размер 1. Типы дают предпросмотр выгоды: boolean — множество из true и false, а присваиваемость — вопрос о подмножестве.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.