4 minute read

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 } } }

Что делать, если нужно сравнивать объекты “по содержимому”?

Если вам нужно сравнивать объекты по их содержимому (глубокое сравнение):

  1. Преобразование объектов в строки 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 }]
    
  2. Использовать сторонние библиотеки, такие как 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.