Preparation Code Preparation HTML (this will be inserted in the <body>
of a valid HTML5 document in standards mode) (useful when testing DOM operations or including libraries) <script src ="https://cdn.jsdelivr.net/npm/dequal@2.0.3/dist/index.min.js" > </script >
<script src ="https://unpkg.com/equivalent-key-map/dist/equivalent-key-map.min.js" > </script >
<script src ="https://cdn.jsdelivr.net/npm/immutable@4.3.7/dist/immutable.min.js" > </script >
Setup JS class DeepMapC {
map = new Map ();
constructor (equals = dequal.dequal ) {
this .equals = equals;
}
findKey (key ) {
for (let k of this .map .keys ()) {
if (this .equals (k, key)) return k;
}
}
set (key, value ) {
this .map .set (this .findKey (key) ?? key, value);
return this ;
}
get (key ) {
const existingKey = this .findKey (key);
if (existingKey) return this .map .get (existingKey);
}
has (key ) {
return !!this .findKey (key);
}
delete (key ) {
const existingKey = this .findKey (key);
if (existingKey) return this .map .delete (existingKey);
else return false ;
}
clear ( ) {
this .map .clear ();
}
get size () {
return this .map .size ;
}
keys ( ) {
return this .map .keys ();
}
values ( ) {
return this .map .values ();
}
entries ( ) {
return this .map .entries ();
}
[Symbol .iterator ]() {
return this .map [Symbol .iterator ]();
}
}
class DeepMapS {
map = new Map ();
keyMap = new Map ();
constructor (serialize, initialValues ) {
this .serialize = serialize;
if (initialValues) {
for (const [key, value] of initialValues) this .set (key, value);
}
}
set (key, value ) {
const keyStr = this .serialize (key);
this .keyMap .set (keyStr, key);
this .map .set (keyStr, value);
return this ;
}
get (key ) {
return this .map .get (this .serialize (key));
}
has (key ) {
return this .keyMap .has (this .serialize (key));
}
delete (key ) {
const keyStr = this .serialize (key);
this .keyMap .delete (keyStr);
return this .map .delete (keyStr);
}
clear ( ) {
this .map .clear ();
this .keyMap .clear ();
}
get size () {
return this .map .size ;
}
keys ( ) {
return this .keyMap .values ();
}
values ( ) {
return this .map .values ();
}
forEach (cb, thisArg ) {
this .keyMap .forEach ((key, keyStr ) => cb.call (thisArg, this .map .get (keyStr), key, this ));
}
copy ( ) {
const newMap = new DeepMap (this .serialize );
newMap.map = new Map (this .map );
newMap.keyMap = new Map (this .keyMap );
return newMap;
}
*entries ( ) {
for (let [keyStr, key] of this .keyMap .entries ()) {
yield [key, this .map .get (keyStr)];
}
}
[Symbol .iterator ]() {
return this .entries ();
}
}
class DeepMapO {
map = {};
keyMap = {};
constructor (serialize, initialValues ) {
this .serialize = serialize;
if (initialValues?.[Symbol .iterator ]) {
for (const [key, value] of initialValues) this .set (key, value);
}
}
set (key, value ) {
const keyStr = this .serialize (key);
this .keyMap [keyStr] = key;
this .map [keyStr] = value;
return this ;
}
get (key ) {
return this .map [this .serialize (key)];
}
has (key ) {
return !!this .map [this .serialize (key)];
}
delete (key ) {
const keyStr = this .serialize (key);
const hasKey = !!this .map [keyStr];
delete this .keyMap [hasKey];
delete this .map [keyStr];
return hasKey;
}
clear ( ) {
this .map = {};
this .keyMap = {};
}
get size () {
return Object .keys (this .map ).length ;
}
*keys ( ) {
for (let keyStr in this .keyMap ) yield this .keyMap [keyStr];
}
*values ( ) {
for (let keyStr in this .keyMap ) yield this .map [keyStr];
}
*entries ( ) {
for (let keyStr in this .keyMap ) yield [this .keyMap [keyStr], this .map [keyStr]];
}
forEach (cb, thisArg ) {
for (let keyStr in this .keyMap ) cb.call (thisArg, this .map [keyStr], this .keyMap [keyStr], this );
}
copy ( ) {
const newMap = new DeepMap O(this .serialize );
newMap.map = { ...this .map };
newMap.keyMap = { ...this .keyMap };
return newMap;
}
[Symbol .iterator ]() {
return this .entries ();
}
}
const serialize = k => `${k.chain} }_{${k.joint} ` ;
const deSerialize = str => {
const parts = str.split ('}_{' );
return { chain : parts[0 ], joint : parts[1 ] };
};
const map = new Map ();
const obj = {};
const mapIsEqual = new DeepMap C(dequal.dequal );
const deepMapMap = new DeepMap S(serialize);
const deepMapObj = new DeepMap O(serialize);
const equivalentKeyMap = new EquivalentKeyMap ();
let immutableMap = new Immutable .Map ();
for (let chain = 0 ; chain < 5 ; chain++) {
for (let joint = 0 ; joint < 10 ; joint++) {
const key = {
chain : `cf221f55-957c-43bf-be45-f5be6d2cebe4-${chain} ` ,
joint : `dc7d8abf-871c-4980-84ed-c7049a67558d-${joint} `
};
const value = `value-${chain} -${joint} ` ;
map.set (serialize (key), value);
obj[serialize (key)] = value;
equivalentKeyMap.set (key, value);
immutableMap = immutableMap.set (Immutable .fromJS (key), value);
mapIsEqual.set (key, value);
deepMapMap.set (key, value);
deepMapObj.set (key, value);
}
}
const testKey = {
chain : `cf221f55-957c-43bf-be45-f5be6d2cebe4-${4 } ` ,
joint : `dc7d8abf-871c-4980-84ed-c7049a67558d-${8 } `
};
Teardown JS