Como você compara dois conjuntos de javascript? Tentei usar ==
e ===
mas ambos retornam falso.
a = new Set([1,2,3]);
b = new Set([1,3,2]);
a == b; //=> false
a === b; //=> false
Esses dois conjuntos são equivalentes, porque por definição, os conjuntos não têm ordem (pelo menos não normalmente). Eu olhei a documentação para Set on MDN e não encontrei nada útil. Alguém sabe como fazer isto?
javascript
set
ecmascript-6
williamcodes
fonte
fonte
===
é para igualdade de valor, não igualdade de objeto.new Set([1,2,3]) != new Set([1,2,3])
. Isso torna o conjunto de Javascript inútil para conjuntos de conjuntos porque o superconjunto conterá subconjuntos duplicados. A única solução alternativa que vem à mente é converter todos os subconjuntos em arrays, classificando cada array e, em seguida, codificando cada array como string (por exemplo JSON).Respostas:
Experimente isto:
Uma abordagem mais funcional seria:
A
all
função funciona para todos os objetos iteráveis (por exemplo,Set
eMap
).Se
Array.from
fosse mais amplamente suportado, poderíamos ter implementado aall
função como:Espero que ajude.
fonte
has
paraisPartOf
ouisIn
ouelem
has
paraisIn
.Você também pode tentar:
fonte
Lodash fornece
_.isEqual()
, que faz comparações profundas. Isso é muito útil se você não quiser escrever o seu próprio. A partir do lodash 4,_.isEqual()
compara corretamente os Conjuntos.fonte
A outra resposta funcionará bem; aqui está outra alternativa.
No entanto, esteja ciente de que isso não faz uma comparação de igualdade profunda. assim
retornará falso. Se os dois conjuntos acima forem considerados iguais, precisamos iterar por ambos os conjuntos, fazendo comparações profundas de qualidade em cada elemento. Estipulamos a existência de uma
deepEqual
rotina. Então a lógica seriaO que isso faz: para cada membro de s1, procure um membro profundamente igual de s2. Se encontrado, exclua-o para que não possa ser usado novamente. Os dois conjuntos são profundamente iguais se todos os elementos em s1 forem encontrados em s2, e s2 se esgotar. Não testado.
Você pode achar isso útil: http://www.2ality.com/2015/01/es6-set-operations.html .
fonte
Nenhuma dessas soluções traz “de volta” a funcionalidade esperada para uma estrutura de dados, como um conjunto de conjuntos. Em seu estado atual, o conjunto de Javascript é inútil para esse propósito porque o superconjunto conterá subconjuntos duplicados, que o Javascript erroneamente considera distintos. A única solução que consigo pensar é converter cada subconjunto em Array , classificá-lo e, em seguida, codificar como String (por exemplo JSON).
Solução
Uso básico
Teste final: conjunto de conjuntos
fonte
[...set1].sort().toString() === [...set2].sort().toString()
A razão pela qual sua abordagem retorna falso é porque você está comparando dois objetos diferentes (mesmo se eles tiverem o mesmo conteúdo), portanto, comparar dois objetos diferentes (não referências, mas objetos) sempre retorna falso.
A abordagem a seguir mescla dois conjuntos em um e simplesmente compara o tamanho. Se for o mesmo, é o mesmo:
Positivo : é muito simples e curto. Sem biblioteca externa, apenas vanilla JS
Desvantagem : provavelmente será mais lento do que apenas iterar os valores e você precisará de mais espaço.
fonte
Comparando dois objetos com ==, ===
Ao usar o operador
==
ou===
para comparar dois objetos, você sempre obterá, afalse
menos que esses objetos façam referência ao mesmo objeto . Por exemplo:Caso contrário, == equivale a falso, embora o objeto contenha os mesmos valores:
Você pode precisar considerar a comparação manual
No ECMAScript 6, você pode converter conjuntos em matrizes de antemão para que possa detectar a diferença entre eles:
NOTA:
Array.from
é um dos recursos padrão do ECMAScript 6, mas não é amplamente compatível com os navegadores modernos. Verifique a tabela de compatibilidade aqui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Browser_compatibilityfonte
b
quais não estãoa
?b
não estãoa
é verificando sea.size === b.size
.a.size === b.size
primeiro em curto-circuito a comparação de elementos individuais, se não for necessário?has
operação em conjuntos é projetada para ser muito eficiente, ao contrário daindexOf
operação em arrays. Portanto, faria sentido alterar sua função de filtro para serreturn !b.has(i)
. Isso também eliminaria a necessidade de converterb
em um array.Eu criei um polyfill rápido para Set.prototype.isEqual ()
Github Gist - Set.prototype.isEqual
fonte
Com base na resposta aceita, assumindo o suporte de
Array.from
, aqui está uma linha:fonte
eqSet = (a,b) => a.size === b.size && [...a].every(b.has.bind(b))
Se os conjuntos contêm apenas tipos de dados primitivos ou objetos dentro dos conjuntos têm igualdade de referência, então há uma maneira mais simples
const isEqualSets = (set1, set2) => (set1.size === set2.size) && (set1.size === new Set([...set1, ...set2]).size);
fonte
Eu sigo esta abordagem nos testes:
fonte
a=[1,2,3]
eb=[1,2,3,4]
, ele dirá que eles são iguais. Então, acho que você precisa de uma verificação extra comosetA.size === setB.size
Modificação muito leve com base na resposta de @Aadit M Shah:
Se alguém mais está tendo problemas como eu devido a alguma peculiaridade da última babel, tinha que adicionar uma condicional explícita aqui.
(Também para o plural eu acho
are
um pouco mais intuitivo de ler em voz alta 🙃)fonte
1) Verifique se os tamanhos são iguais. Se não, eles não são iguais.
2) itere sobre cada elemento de A e verifique se existe em B. Se um falhar, retornar
unequal
3) Se as 2 condições acima falharem, significa que são iguais.
2) Método 2
fonte
forEach
método NÃO fará com que a função pai retorne.