Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между Set и массивом?
Set и массив — это две разные структуры данных в JavaScript, каждая со своими преимуществами и недостатками. Выбор между ними зависит от конкретной задачи.
Основные различия
1. Уникальность значений
Массив может содержать дубликаты:
const array = [1, 2, 2, 3, 3, 3];
console.log(array.length); // 6
Set хранит только уникальные значения:
const set = new Set([1, 2, 2, 3, 3, 3]);
console.log(set.size); // 3
2. Структура и производительность
Массив:
- Упорядоченная коллекция элементов
- Доступ по индексу: O(1)
- Поиск элемента: O(n)
- Удаление элемента: O(n)
Set:
- Коллекция уникальных значений
- Нет доступа по индексу
- Проверка наличия: O(1)
- Удаление элемента: O(1)
3. Использование памяти
// Для проверки наличия элемента
// Массив - неэффективно для больших данных
const array = [1, 2, 3, 4, 5, 100000];
array.includes(99999); // O(n) - проверяет все элементы
// Set - очень быстро
const set = new Set([1, 2, 3, 4, 5, 100000]);
set.has(99999); // O(1) - прямая проверка
Создание
Массив
// Литеральная нотация
const array1 = [1, 2, 3];
// Конструктор Array
const array2 = new Array(1, 2, 3);
// Из другого итерируемого объекта
const array3 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Set
// Конструктор Set (принимает итерируемый объект)
const set1 = new Set([1, 2, 2, 3]);
console.log(set1.size); // 3
// Пустой Set
const set2 = new Set();
// Из строки
const set3 = new Set('hello');
console.log(set3); // Set(4) { 'h', 'e', 'l', 'o' }
Методы и свойства
Массив
const array = [1, 2, 3];
// Свойства
array.length; // 3
// Методы
array.push(4); // Добавить в конец
array.pop(); // Удалить последний
array.shift(); // Удалить первый
array.unshift(0); // Добавить в начало
array.includes(2); // Проверить наличие
array.indexOf(2); // Найти индекс
array.filter(x => x > 1); // Отфильтровать
array.map(x => x * 2); // Преобразовать
Set
const set = new Set([1, 2, 3]);
// Свойства
set.size; // 3
// Методы
set.add(4); // Добавить элемент
set.delete(2); // Удалить элемент
set.has(2); // Проверить наличие
set.clear(); // Очистить Set
set.values(); // Итератор по значениям
set.keys(); // Итератор по ключам (= values в Set)
set.entries(); // Итератор по парам [value, value]
set.forEach(callback); // Итерация
// Преобразование в массив
Array.from(set); // [1, 2, 3]
[...set]; // [1, 2, 3]
Сравнение производительности
Проверка наличия элемента
// Генерируем большой массив
const largeArray = Array.from({length: 100000}, (_, i) => i);
const largeSet = new Set(largeArray);
// Проверка в массиве - медленно
console.time('Array.includes');
for (let i = 0; i < 1000; i++) {
largeArray.includes(99000); // O(n)
}
console.timeEnd('Array.includes'); // ~100ms
// Проверка в Set - быстро
console.time('Set.has');
for (let i = 0; i < 1000; i++) {
largeSet.has(99000); // O(1)
}
console.timeEnd('Set.has'); // ~1ms
Практические примеры
1. Удаление дубликатов из массива
// Способ 1: использование Set
const array = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(array)];
console.log(unique); // [1, 2, 3, 4]
// Способ 2: фильтрация
const unique2 = array.filter((v, i) => array.indexOf(v) === i);
2. Пересечение двух массивов
const array1 = [1, 2, 3, 4];
const array2 = [3, 4, 5, 6];
const set1 = new Set(array1);
const intersection = array2.filter(x => set1.has(x));
console.log(intersection); // [3, 4]
3. Проверка наличия ID пользователя в списке запрещенных
// Плохо: O(n) для каждой проверки
const bannedUserIds = [123, 456, 789, ...];
function isUserBanned(userId) {
return bannedUserIds.includes(userId); // медленно
}
// Хорошо: O(1) для каждой проверки
const bannedUserSet = new Set([123, 456, 789, ...]);
function isUserBanned(userId) {
return bannedUserSet.has(userId); // быстро
}
4. Отслеживание посещённых элементов
function findPath(graph, start, end) {
const visited = new Set(); // O(1) проверка
function dfs(node) {
if (visited.has(node)) return false;
if (node === end) return true;
visited.add(node);
for (const neighbor of graph[node]) {
if (dfs(neighbor)) return true;
}
return false;
}
return dfs(start);
}
5. Кэширование результатов
const cache = new Set();
function expensiveOperation(value) {
if (cache.has(value)) {
console.log('Из кэша');
return value;
}
console.log('Вычисляем...');
cache.add(value);
return value * 2;
}
expensiveOperation(5); // Вычисляем...
expensiveOperation(5); // Из кэша
Итерация
Массив
const array = [1, 2, 3];
// for-of
for (const value of array) {
console.log(value);
}
// forEach
array.forEach((value, index) => {
console.log(index, value);
});
// map, filter, reduce
array.map(x => x * 2);
Set
const set = new Set([1, 2, 3]);
// for-of
for (const value of set) {
console.log(value);
}
// forEach
set.forEach((value) => {
console.log(value);
});
// Преобразуем в массив и используем методы массива
[...set].map(x => x * 2);
Когда использовать Set?
- Проверка наличия элемента в большом наборе данных
- Удаление дубликатов
- Реализация алгоритмов графов (посещённые узлы)
- Кэширование уникальных значений
- Работа с уникальными ID
- Когда не нужен доступ по индексу
Когда использовать массив?
- Нужна упорядоченность и доступ по индексу
- Часто нужны методы преобразования (map, filter, reduce)
- Нужны дубликаты
- Нужна совместимость с JSON (JSON.stringify)
- Проще в использовании для простых случаев
Гибридный подход
// Используем Set для быстрой проверки
const userIds = [1, 2, 3, 4, 5];
const userSet = new Set(userIds);
function processUsers(ids) {
const results = [];
for (const id of ids) {
if (userSet.has(id)) {
results.push(getUserData(id)); // O(1) проверка
}
}
return results;
}
Резюме
| Характеристика | Массив | Set |
|---|---|---|
| Уникальность | Может быть дубликаты | Только уникальные |
| Доступ по индексу | Да O(1) | Нет |
| Проверка наличия | Медленно O(n) | Быстро O(1) |
| Удаление | Медленно O(n) | Быстро O(1) |
| Методы преобразования | Много (map, filter) | Мало |
| JSON.stringify | Работает | Нужна конвертация |
Выводы:
- Set лучше для проверки наличия и уникальности
- Массив лучше для упорядоченности и преобразований
- Часто используют оба вместе для оптимальной производительности