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.