Множества (Set) в TypeScript 5 (Node.js): полное руководство для начинающих
Множества (Set) в TypeScript
Представь, что у тебя есть коробка, в которую можно класть только уникальные предметы. Если ты попробуешь положить туда два одинаковых мячика, второй просто не поместится — он уже там есть! Именно так работает структура данных Set (Множество) в TypeScript.
Множество — это коллекция, которая хранит только уникальные значения. В отличие от массива, где элементы могут повторяться, в Set каждый элемент встречается только один раз. Это очень удобно, когда нужно, например, собрать список всех посетителей сайта без повторений или найти уникальные теги в статье.
Создание множества
Чтобы создать пустое множество, используй конструктор new Set(). Можно сразу передать массив с начальными значениями:
// Пустое множество
const emptySet = new Set<number>();
// Множество с начальными значениями
const fruits = new Set<string>(["яблоко", "банан", "апельсин"]);
// Множество с числами
const numbers = new Set<number>([1, 2, 3, 2, 1]); // Будет {1, 2, 3}
Основные операции с Set
Вот главные методы, которые нужно знать:
- add(value) — добавляет элемент в множество. Если элемент уже есть, ничего не происходит.
- delete(value) — удаляет элемент. Возвращает true, если элемент был удалён, и false, если его не было.
- has(value) — проверяет, есть ли элемент в множестве. Возвращает true или false.
- clear() — удаляет все элементы из множества.
- size — свойство, показывающее количество элементов (не метод, а свойство!).
const colors = new Set<string>();
// Добавляем элементы
colors.add("красный");
colors.add("синий");
colors.add("зеленый");
colors.add("красный"); // Не добавится — уже есть!
console.log(colors.size); // 3
// Проверяем наличие
console.log(colors.has("синий")); // true
console.log(colors.has("желтый")); // false
// Удаляем элемент
colors.delete("зеленый");
console.log(colors.size); // 2
// Очищаем всё множество
colors.clear();
console.log(colors.size); // 0
Перебор элементов множества
Множество можно перебирать с помощью цикла for...of или метода forEach:
const animals = new Set<string>(["кот", "собака", "попугай"]);
// Способ 1: for...of
for (const animal of animals) {
console.log(animal);
}
// Способ 2: forEach
animals.forEach((animal) => {
console.log(animal);
});
Преобразование Set в массив и обратно
Очень часто нужно превратить множество в массив или наоборот. Для этого используй оператор ... (spread) или Array.from():
// Из Set в массив
const set = new Set<number>([1, 2, 3, 4, 5]);
const arr = [...set]; // [1, 2, 3, 4, 5]
// Или так: const arr = Array.from(set);
// Из массива в Set (убираем дубликаты)
const numbers = [1, 2, 2, 3, 3, 3, 4];
const uniqueNumbers = new Set<number>(numbers);
console.log([...uniqueNumbers]); // [1, 2, 3, 4]
Пример: программа для подсчёта уникальных слов
Давай напишем программу, которая читает строку текста и выводит количество уникальных слов в ней:
import * as readline from 'readline';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Введите текст: ', (text: string) => {
// Разбиваем текст на слова (убираем знаки препинания)
const words = text.toLowerCase().match(/[а-яёa-z]+/g) || [];
// Создаём множество уникальных слов
const uniqueWords = new Set<string>(words);
console.log(`Всего слов: ${words.length}`);
console.log(`Уникальных слов: ${uniqueWords.size}`);
rl.close();
});
Типичные задачи с Set
Задача 1. Удаление дубликатов из массива
Самая популярная задача — убрать повторяющиеся элементы из массива:
function removeDuplicates<T>(arr: T[]): T[] {
return [...new Set<T>(arr)];
}
const numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5];
console.log(removeDuplicates(numbers)); // [1, 2, 3, 4, 5]
Задача 2. Проверка пересечения двух множеств
Нужно найти общие элементы в двух коллекциях:
function findIntersection<T>(arr1: T[], arr2: T[]): T[] {
const set1 = new Set<T>(arr1);
const set2 = new Set<T>(arr2);
const result: T[] = [];
for (const item of set1) {
if (set2.has(item)) {
result.push(item);
}
}
return result;
}
const group1 = ["Аня", "Боря", "Витя", "Галя"];
const group2 = ["Боря", "Галя", "Дима", "Ева"];
console.log(findIntersection(group1, group2)); // ["Боря", "Галя"]
Задача 3. Разность множеств
Найти элементы, которые есть в первом множестве, но нет во втором:
function findDifference<T>(arr1: T[], arr2: T[]): T[] {
const set2 = new Set<T>(arr2);
return arr1.filter(item => !set2.has(item));
}
const allStudents = ["Аня", "Боря", "Витя", "Галя", "Дима"];
const present = ["Аня", "Витя", "Дима"];
console.log(findDifference(allStudents, present)); // ["Боря", "Галя"]
Частые ошибки и как их избежать
Ошибка 1: Путать Set с Map
Set хранит только значения, а Map хранит пары ключ-значение. Не пытайся использовать Set как словарь!
// ❌ Неправильно
const badSet = new Set<string, number>(); // Ошибка! Set принимает только один тип
// ✅ Правильно
const goodSet = new Set<string>();
Ошибка 2: Думать, что Set сохраняет порядок
Set сохраняет порядок добавления элементов, но не сортирует их автоматически. Если нужна сортировка, преобразуй в массив:
const nums = new Set<number>([3, 1, 2]);
console.log([...nums]); // [3, 1, 2] — порядок добавления
// Если нужна сортировка:
const sorted = [...nums