2016-05-06 2 views
2

В Python, можно иметь набор множеств с помощью frozenset:Набор множеств (множеств ...)

s, t = frozenset([1]), frozenset([1]) 
u = {s, t} # u == {frozenset([1])} 

Теперь, ECMAScript 6 приносит Set объект, есть ли способ JavaScript должен иметь набор, содержащий другие множества, однозначно, т.е. отказаться от всех наборов, кроме одного, имеющих одни и те же элементы?

Я спрашиваю, потому что это не работает:

var s = new Set([1]), t = new Set([1]); 
var u = new Set([s, t]); // u == Set{Set{1}, Set{1}} 

Я понимаю, что, вероятно, Set хэш указателей других наборов она включает в себя, именно поэтому два {1} появляются различны. Я спрашиваю, есть ли способ в JavaScript для достижения описанного выше поведения Python.

+0

Поведение верное. Множества 's' и' t' - разные объекты, поэтому они должны быть разными. – trincot

+3

* «Я спрашиваю, есть ли способ JavaScript для достижения поведения Python, описанного выше». * Нет. JavaScript не имеет способа определить равномерность объекта. –

+0

@FelixKling Если это действительно так, пожалуйста, напишите свой ответ ниже, я приму его. –

ответ

0

Это потому, что значения JavaScript, являющиеся объектами, считаются равными, только если они являются одним и тем же объектом. Например, {} === {} оценивает по: false.

Как указано в @torazaburo, вы можете создать прокси-сервер для этого набора, который будет обходить вызовы .add() и пропускать элементы, которые равны любому из существующих членов. Вы можете использовать функцию _.isEqual() из библиотеки lodash для сравнения двух наборов.

const firstSet = new Set([1]) 
    ,secondSet = new Set([1]) 

const newSet = new Set() 

newSet.add = new Proxy(newSet.add, { 
    apply: (target, thisArg, [value])=> { 
    // Array.from() is required to use Array.prototype.some() 
    if (!Array.from(newSet).some(element=> _.isEqual(element, value))) { 
     target.call(newSet, value) 
    } 
    return target 
    } 
}) 

newSet.add(firstSet) 
newSet.add(secondSet) 

console.log(newSet.has(firstSet)) // logs true 
console.log(newSet.has(secondSet)) // logs false, because secondSet 
            // has not been added, since it's a duplicate 
console.log(newSet.size)   // logs 1 

См. JS Bin demo.

+0

Я не так хорошо разбираюсь в JavaScript, но разве это не означает, что 'apply' запускается в O (n)? Я имею в виду, что это в основном выполняет итерации по всем уже включенным наборам и сравнивает каждый с «Array.isEqual» в другом O (n)? Чем это отличается от использования массивов вместо наборов? –

+0

@ EcirHana Вы правы, это ничем не отличается от использования массивов. –