Set vs Array
1. Основные различия
| Характеристика | Array | Set |
|---|---|---|
| Дублирующиеся элементы | Разрешены | Уникальные значения (дубликаты не допускаются) |
| Порядок элементов | Сохраняется | Сохраняется |
| Тип данных | Может содержать любые значения (включая дубликаты) | Хранит только уникальные значения |
| Размер | array.length |
set.size |
| Методы доступа | Обращение по индексу (array[0]) |
Нет доступа по индексу |
2. Когда использовать Set
-
Уникальные значения: Если нужно хранить только уникальные элементы,
Set— лучший выбор.const uniqueSet = new Set([1, 2, 3, 3, 4]); console.log([...uniqueSet]); // [1, 2, 3, 4] -
Быстрая проверка наличия элемента: Проверка элемента (
set.has()) вSetвыполняется быстрее, чем в массиве (array.includes()), особенно для больших коллекций.const set = new Set([1, 2, 3]); console.log(set.has(2)); // true -
Добавление/удаление элемента: Добавление и удаление элемента в
Setбыстрее, чем в массиве, поскольку не нужно проверять дубликаты.set.add(4); // Добавить элемент set.delete(2); // Удалить элемент
3. Когда использовать Array
-
Упорядоченные данные: Если порядок и индекс элементов важен, то массив подходит больше.
const array = [1, 2, 3, 4]; console.log(array[2]); // 3 -
Дубликаты допустимы: Когда коллекция может содержать повторяющиеся значения.
const array = [1, 2, 2, 3, 4]; console.log(array); // [1, 2, 2, 3, 4] -
Методы для работы с массивами: У массивов больше встроенных методов (например,
map,filter,reduce), что делает их удобнее для обработки данных.
4. Производительность
| Операция | Array | Set |
|---|---|---|
| Поиск элемента | Медленнее (O(n)), так как проверяет каждый элемент | Быстрее (O(1)), так как использует хэширование |
| Добавление элемента | Быстрее, но возможны дубликаты | Быстрее, если нужно учитывать уникальность |
| Удаление элемента | Медленнее, так как нужно найти элемент (O(n)) | Быстрее, так как использует хэширование |
5. Примеры использования
- Когда использовать
Set:-
Устранение дубликатов из массива.
const array = [1, 2, 3, 3, 4, 4]; const unique = [...new Set(array)]; console.log(unique); // [1, 2, 3, 4] -
Быстрая проверка наличия элементов.
const set = new Set(['apple', 'banana', 'orange']); console.log(set.has('banana')); // true
-
- Когда использовать
Array:-
Хранение данных с повторяющимися элементами или упорядоченными индексами.
const fruits = ['apple', 'apple', 'banana']; console.log(fruits[0]); // 'apple' -
Работа с массивом через встроенные методы.
const numbers = [1, 2, 3, 4]; const squared = numbers.map(n => n * n); console.log(squared); // [1, 4, 9, 16]
-
Итог: Что быстрее?
- Если нужна уникальность данных или частые проверки на наличие,
Setбыстрее, чем массив. - Если важен порядок или требуются сложные операции с данными, лучше использовать массив.
Рекомендация: Используйте Set, если:
- Элементы должны быть уникальными.
- Нужна высокая производительность при проверке наличия элемента. Во всех остальных случаях массив остаётся универсальным инструментом.
Методы вроде reduce, map, filter не поддерживаются у Set напрямую, потому что Set — это не массив. Однако, можно легко преобразовать Set в массив, чтобы использовать эти методы.
Как работать с первыми 250 элементами из Set
1. Преобразование Set в массив
Для того чтобы использовать массивные методы, нужно превратить Set в массив с помощью Array.from() или спред-оператора ....
const mySet = new Set([...Array(300).keys()]); // Создаём Set с числами от 0 до 299
const first250 = Array.from(mySet).slice(0, 250); // Берём первые 250 элементов
console.log(first250);
Или с использованием спред-оператора:
const first250 = [...mySet].slice(0, 250);
console.log(first250);
2. Использование цикла
Если вы хотите работать с элементами прямо из Set без преобразования:
const mySet = new Set([...Array(300).keys()]);
const first250 = [];
let count = 0;
for (const item of mySet) {
if (count === 250) break; // Останавливаемся после 250 элементов
first250.push(item);
count++;
}
console.log(first250);
Итог: Какой способ выбрать?
- Для краткости: Используйте
Array.from(mySet).slice(0, 250)или[...mySet].slice(0, 250). - Для оптимизации без преобразования: Используйте цикл
for...of.
Обратите внимание, что порядок элементов в Set сохраняется, поэтому первые 250 элементов будут извлечены в том же порядке, в каком они были добавлены.
Сравнение объектов в Set
Вложенные структуры (многослойные объекты)
Set не проводит глубокое сравнение для вложенных объектов. Для Set вложенные объекты остаются объектами, сравниваемыми по ссылке. Например:
const obj1 = { a: { b: 2 } };
const obj2 = { a: { b: 2 } }; // Тот же самый "содержательный" объект, но другая ссылка
const mySet = new Set();
mySet.add(obj1);
mySet.add(obj2); // Добавится, потому что это другая ссылка
console.log(mySet.size); // 2
console.log(mySet); // Set { { a: { b: 2 } }, { a: { b: 2 } } }
Что делать, если нужно сравнивать объекты “по содержимому”?
Если вам нужно сравнивать объекты по их содержимому (глубокое сравнение):
-
Преобразование объектов в строки JSON:
const mySet = new Set(); mySet.add(JSON.stringify({ a: 1 })); mySet.add(JSON.stringify({ a: 1 })); // Не добавится, потому что строка идентична console.log(mySet); // Set { '{"a":1}' }Чтобы использовать объекты снова, можно парсить JSON:
const parsedSet = Array.from(mySet).map(item => JSON.parse(item)); console.log(parsedSet); // [{ a: 1 }] -
Использовать сторонние библиотеки, такие как Lodash: Вы можете проверить объекты на равенство перед добавлением с помощью
_.isEqualиз Lodash:const _ = require('lodash'); const mySet = new Set(); const obj1 = { a: 1 }; const obj2 = { a: 1 }; if (![...mySet].some(item => _.isEqual(item, obj1))) { mySet.add(obj1); } if (![...mySet].some(item => _.isEqual(item, obj2))) { mySet.add(obj2); } console.log(mySet); // Set { { a: 1 } }
Итог
- Примитивы в
Setсравниваются по значению. - Объекты и массивы сравниваются по ссылке (не по содержимому).
- Для глубокого сравнения вам нужно использовать дополнительные подходы, такие как преобразование в строки (JSON) или сравнение с помощью библиотек вроде Lodash.