Created
November 3, 2023 10:03
-
-
Save phillippelevidad/d44aef576dd9f97e046987302992dbf8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The UniquePropertySet class is designed to manage a collection of objects, | |
* ensuring that each object is unique based on its properties and values | |
* rather than its reference in memory. | |
* | |
* Beware, though, that this implementation is not optimized for performance, | |
* and that the JSON.stringify method does not handle non-serializable values | |
* consistently, such as functions, undefined, or circular references, which | |
* will cause objects containing such values to not be handled correctly. | |
*/ | |
class UniquePropertySet { | |
constructor() { | |
this.map = new Map(); | |
} | |
add(obj) { | |
const key = this._serialize(obj); | |
if (!this.map.has(key)) { | |
this.map.set(key, obj); | |
} | |
} | |
has(obj) { | |
const key = this._serialize(obj); | |
return this.map.has(key); | |
} | |
delete(obj) { | |
const key = this._serialize(obj); | |
return this.map.delete(key); | |
} | |
_serialize(obj) { | |
// Sort the object's keys to ensure consistent order | |
return JSON.stringify(obj, Object.keys(obj).sort()); | |
} | |
clear() { | |
return this.map.clear(); | |
} | |
get size() { | |
return this.map.size; | |
} | |
values() { | |
return this.map.values(); | |
} | |
*[Symbol.iterator]() { | |
for (let value of this.map.values()) yield value; | |
} | |
} | |
// Usage | |
const assert = require("assert"); | |
const uniqueObjects = new UniquePropertySet(); | |
uniqueObjects.add({ a: 1, b: 2 }); | |
uniqueObjects.add({ b: 2, a: 1 }); // Won't be added, as it's considered a duplicate | |
assert.strictEqual(uniqueObjects.size, 1); | |
uniqueObjects.add({ a: 1, b: 2, c: 3 }); // Will be added, as it's a different object | |
assert.strictEqual(uniqueObjects.size, 2); | |
uniqueObjects.delete({ a: 1, b: 2 }); // Correctly deletes the first entry | |
assert.strictEqual(uniqueObjects.size, 1); | |
// Nested objects are supported too | |
uniqueObjects.clear(); | |
uniqueObjects.add({ a: 1, b: { c: 2 } }); | |
uniqueObjects.add({ a: 1, b: { c: 2 } }); | |
assert.strictEqual(uniqueObjects.size, 1); | |
// Even nested objects are supported | |
uniqueObjects.clear(); | |
uniqueObjects.add({ a: 1, b: { d: 3, c: 2 } }); | |
uniqueObjects.add({ a: 1, b: { c: 2, d: 3 } }); | |
assert.strictEqual(uniqueObjects.size, 1); |
Opa, iae blz? era isso msm "Daí, se eu entendi bem a sua dúvida aqui, é porque você está curioso se fazer um for..of resolveria, ou seja, se seria mais rápido" eu ainda ñ chegai nesse módulo ainda "benchmark" msm valeuzão pela resposta...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Vi meu comentário na aula de Set e WeakSet. Lá eu falei que essa solução que eu botei aqui no Gist tem um problema inerente de performance porque usa JSON.stringify. Daí, se eu entendi bem a sua dúvida aqui, é porque você está curioso se fazer um for..of resolveria, ou seja, se seria mais rápido.
Em tese, sim :) mas só tem um jeito da gente saber, e é fazendo um benchmark. O Erick ensina isso mais à frente no curso, mas bora rodar um benchmark aqui rapidão e ver o que acontece.
Rodei o código abaixo 3 vezes, pra gente ter uma análise melhor de 3, e olha só os tempos:
Você pode ver que, no último teste, o deepEqual rodou 944.692 por segundo, contra apenas 88.985 do JSON.stringify. E os outros dois testes não ficam muito diferentes, então podemos que, na média, o deepEqual que mandei pra você no comentário acima é 10x mais rápido que o JSON.stringify!
Segue o código do teste, usando a lib https://www.npmjs.com/package/benchmark. Eu crio dois objetos idênticos e deixo rodar a comparação nas duas formas que estamos testando.
Massa, né :)