Способы создания набора в JavaScript?


в Eloquent JavaScript, Глава 4, набор значений создается путем создания объекта и хранения значений в качестве имен свойств, присваивая произвольные значения (например, true) в качестве значений свойств. Чтобы проверить, если значение уже содержится в наборе,in оператор используется:

var set = {};

if (!'Tom' in set) { 
  set.Tom = true;
}

это идиоматический JavaScript? Не будет ли использование массива еще лучше?

var set = [];

if (!'Tom' in set) { 
  set.push = 'Tom';
}
7 54

7 ответов:

наборы теперь доступны в ES2015 (aka ES6, т. е. ECMAScript 6). ES6 является текущим стандартом для JavaScript с июня 2015 года.

ECMAScript 6 имеет набор структур данных, который работает для произвольных значения, быстро и обрабатывает NaN правильно. - Аксель Rauschmayer,изучение ES6

первые два примера из от Axel Rauschmayer-х книги знакомства ES6:

управление отдельными элементами:

> let set = new Set();
> set.add('red')

> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false

определение размера набора и его очистка:

> let set = new Set();
> set.add('red')
> set.add('green')

> set.size
2
> set.clear();
> set.size
0

Я бы проверил изучение ES6 если вы хотите узнать больше о наборах в JavaScript. Книга бесплатно читать онлайн, но если вы хотите поддержать автора Д-Р Аксель Rauschmayer вы можете приобрести книгу около 30$.

Если вы хотите использовать наборы и ES6 теперь вы можете использовать Бабель, транспилер ES6-ES5 и его полифиллы.

Edit: по состоянию на 6 июня 2017 года большинство основных браузеров имеют полную поддержку набора в своих последних версиях (кроме IE 11). Это означает, что вам может не понадобиться babel, если вы не хотите поддерживать старые браузеры. Если вы хотите видеть совместимость в разных браузерах, включая ваш текущий браузер, проверьте таблица совместимости ES6 Kangax.

Я использую объекты dict в качестве наборов. Это работает со строками и числами, но я полагаю, что это вызовет проблемы, если вы хотите иметь набор объектов, использующих пользовательские операторы равенства и сравнения:

создание набора:

var example_set = 
{
    'a':true,
    'b':true,
    'c':true
}

тестирование для включения в набор

if( example_set['a'] ){
    alert('"a" is in set');
}

добавление элемента в набор

example_set['d'] = true;

удаление элемента из a набор

delete example_set['a'];

наборы не позволяют дублировать записи и обычно не гарантируют предопределенного заказа. Массивы делают оба из них, тем самым нарушая то, что означает быть набором (если вы не выполняете дополнительные проверки).

первый способ-это идиоматический JavaScript.

каждый раз, когда вы хотите сохранить пару ключ/значение, вы должны использовать объект JavaScript. Что касается массивов, есть несколько проблем:

  1. индекс-это числовое значение.

  2. нет простого способа проверить, находится ли значение в массиве без цикла.

  3. набор не допускает дубликатов. Массив делает.

Если вы хотите создать набор из массива, просто:

let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }

это синтаксис сахара, который мне очень понравился при программировании на Python, поэтому я рад, что ES6 наконец-то позволил сделать то же самое.

Примечание: тут я понимаю что я сказал не прямо ответить на ваш вопрос. Причина, по которой у вас есть этот "хак" в ES5, заключается в том, что время поиска в объекте по ключам значительно быстрее (O(1)), чем в массиве (O(n)). В критически важных для производительности приложениях вы может пожертвовать этим битом читаемости или интуиции для лучшей производительности.

но эй, добро пожаловать в 2017, где вы можете использовать правильный Set во всех основных современных браузерах сейчас!

есть две проблемы с использованием голых объектов javascript для эмуляции наборов: во-первых, объект может иметь наследуемое свойство, которое будет завинчивать оператор "in", а во-вторых, вы можете хранить только скалярные значения таким образом, что создание набора объектов невозможно. Таким образом, реалистичность реализации комплектов должны быть предусмотрены способы add и contains вместо in и присвоения имущества.

вы можете попробовать ведра, это библиотека структуры данных javascript и имеет все необходимое для управления наборами.