Multikeys data structures collection written in TypeScript: Map, Set, WeakMap and WeakSet. Based on trie data structure.
Benchmarks 🚀
Benchmarks are located in ./benchmark
directory. You can modify ./benchmark/index.js
and run npm i && npm start
to test your own use cases.
Results of calling set
and get
with random data (and random number of keys). You can find benchmark code in ./benchmark/index.js
.
package | set and get (ops/sec) | normalized on many-keys-map |
---|---|---|
multikeymap | 1.37 ±19.20% | 0 |
many-keys-map | 27 795 ±0.84% | 1 |
multikey | 79 355 ±1.37% | 2.85 |
multikey-map | 153 616 ±1.32% | 5.52 |
multikeys | 185 565 ±1.70% | 6.67 |
package | set and get (ops/sec) | normalized on many-keys-map |
---|---|---|
multikeymap | fall with OOM | - |
many-keys-map | 7 120 ±0.92% | 1 |
multikey | 10 830 ±1.35% | 1.52 |
multikey-map | 29 635 ±1.26% | 4.16 |
multikeys | 43 394 ±1.52% | 6.09 |
const mkMap = new MKMap();
mkMap.set([1, 2, 3], "foo");
mkMap.set([3, 2, 1], "bar");
// order of keys matters
mkMap.get([1, 2, 3]); // => 'foo'
mkMap.get([3, 2, 1]); // => 'bar'
// an argument with empty keys is also valid
mkMap.set([], "zero");
mkMap.get([]); // => 'zero'
const mkSet = new MKSet();
const obj = {};
mkSet.add([obj, 1]);
mkSet.has([{}, 1]); // => false, because {} is a new object, {} !== obj
mkSet.has([obj, 1]); // => true
Using MKMap we could simply add memoization to function with a variable number of arguments:
const { MKMap } = require("multikeys");
function memoize(func) {
const mkMap = new MKMap();
return (...args) => {
if (mkMap.has(args)) {
return mkMap.get(args);
}
const res = func(...args);
mkMap.set(args, res);
return res;
};
}
Also, we could replace MKMap
with MKWeakMap
and get memoize
with auto garbage collection. In such case only objects could be func
arguments.
Name | Type |
---|---|
K |
any |
V |
any |
• new MKMap<K
, V
>(iterable?
)
Creates a new MKMap object.
Could be called with initial keys-values.
const empty = new MKMap();
const withValues = new MKMap([
[['key_1', 'key_2'], 'value'],
[['key'], 'val']
]);
Name | Type |
---|---|
K |
any |
V |
any |
Name | Type |
---|---|
iterable? |
Iterable <readonly [readonly K [], V ]> |
• get
size(): number
Returns the number of keys/value pairs in the MKMap object.
number
▸ [iterator](): IterableIterator
<[K
[], V
]>
Returns a new Iterator object that contains an array of [keys, value] for each element in the MKMap object.
IterableIterator
<[K
[], V
]>
▸ clear(): void
Removes all keys-value pairs from the MKMap object.
void
▸ delete(keys
): boolean
Returns true if an element in the MKMap object existed and has been removed, or false if the element does not exist.
const mkMap = new MKMap([['foo'], 'bar']);
mkMap.delete(['foo']); // => true
mkMap.delete(['foo']); // => false
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ entries(): IterableIterator
<[K
[], V
]>
Returns a new Iterator object that contains an array of [keys, value] for each element in the Map object.
IterableIterator
<[K
[], V
]>
▸ forEach(callbackFn
): void
Calls callbackFn once for each keys-value pair present in the MKMap object.
Name | Type |
---|---|
callbackFn |
(value : V , keys : K [], map : MKMap <K , V >) => void |
void
▸ get(keys
): undefined
| V
Returns the value associated to the keys, or undefined if there is none.
const mkMap = new MKMap([['foo'], 'bar']);
mkMap.get(['foo']); // => 'bar'
Name | Type |
---|---|
keys |
readonly K [] |
undefined
| V
▸ has(keys
): boolean
Returns a boolean asserting whether a value has been associated to the keys in the MKMap object or not.
const mkMap = new MKMap([['foo'], 'bar']);
mkMap.has(['foo']); // => true
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ keys(): IterableIterator
<K
[]>
Returns a new Iterator object that contains the keys for each element in the MKMap.
IterableIterator
<K
[]>
▸ set(keys
, value
): MKMap
<K
, V
>
Sets the value for the keys in the MKMap object. Returns the MKMap object.
mkMap.set(['foo'], 'bar');
Name | Type |
---|---|
keys |
readonly K [] |
value |
V |
MKMap
<K
, V
>
▸ values(): IterableIterator
<V
>
Returns a new Iterator object that contains the values for each element in the MKMap object.
IterableIterator
<V
>
Name | Type |
---|---|
K |
any |
• new MKSet<K
>(iterable?
)
Creates a new MKSet object.
Could be called with initial keys.
const empty = new MKSet();
const withKeys = new MKSet([
['key'],
['few', 'keys']
]);
Name | Type |
---|---|
K |
any |
Name | Type |
---|---|
iterable? |
Iterable <readonly K []> |
• get
size(): number
Returns the number of values in the MKSet object.
number
▸ [iterator](): IterableIterator
<K
[]>
Returns a new Iterator object that yields the keys for each element in the MKSet object.
IterableIterator
<K
[]>
▸ add(keys
): void
Appends keys to the MKSet object.
mkSet.add([1, 2, 3]);
Name | Type |
---|---|
keys |
readonly K [] |
void
▸ clear(): void
Removes all elements from the MKSet object.
void
▸ delete(keys
): boolean
Removes the element associated to the keys and returns the value that MKSet.has(keys) would have previously returned. MKSet.has(keys) will return false afterwards.
const mkSet = new MKSet([['foo']]);
mkSet.delete(['foo']); // => true
mkSet.delete(['foo']); // => false
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ entries(): IterableIterator
<[K
[], K
[]]>
Returns a new Iterator object that contains an array of [keys, keys] for each element in the MKSet object.
IterableIterator
<[K
[], K
[]]>
▸ forEach(callbackFn
): void
Calls callbackFn once for each value present in the MKSet object.
Name | Type |
---|---|
callbackFn |
(value : K [], key : K [], map : MKSet <K >) => void |
void
▸ has(keys
): boolean
Returns a boolean asserting whether an element is present with the given keys in the MKSet object or not.
const mkSet = new MKSet([['foo']]);
mkSet.has(['foo']); // => true
mkSet.has(['bar']); // => false
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ keys(): IterableIterator
<K
[]>
Returns a new Iterator object that yields the keys for each element in the MKSet object. (this is the same as the values() method.)
IterableIterator
<K
[]>
▸ values(): IterableIterator
<K
[]>
Returns a new Iterator object that yields the keys for each element in the MKSet object. (this is the same as the keys() method.)
IterableIterator
<K
[]>
Name | Type |
---|---|
K |
extends object = object |
V |
any |
• new MKWeakMap<K
, V
>(iterable?
)
Creates a new MKWeakMap object.
Could be called with initial keys-values
const empty = new MKWeakMap();
const withValues = new MKWeakMap([
[[{foo: 'bar'}], 'val']
]);
Name | Type |
---|---|
K |
extends object = object |
V |
any |
Name | Type |
---|---|
iterable? |
Iterable <readonly [readonly K [], V ]> |
▸ delete(keys
): boolean
Removes any value associated to the keys. Returns true if an element in the MKWeakMap object has been removed successfully.
const obj = {};
const mkWeakMap = new MKWeakMap([[obj, 'foo']]);
mkWeakMap.delete([obj]); // => true
mkWeakMap.delete([obj]); // => false
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ get(keys
): undefined
| V
Returns the value associated to the keys, or undefined if there is none.
const obj = {};
const mkWeakMap = new MKWeakMap([[obj, 'foo']]);
mkWeakMap.get([obj]); // => 'foo'
Name | Type |
---|---|
keys |
readonly K [] |
undefined
| V
▸ has(keys
): boolean
Returns a Boolean asserting whether a value has been associated to the keys in the MKWeakMap object or not.
const obj = {};
const mkWeakMap = new MKWeakMap([[obj, 'foo']]);
mkWeakMap.has([obj]); // => 'true'
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ set(keys
, value
): MKWeakMap
<K
, V
>
Sets the value for the keys in the MKWeakMap object. Returns the MKWeakMap object.
const mkWeakMap = new MKWeakMap();
const obj = {};
mkWeakMap.set([obj], 'foo');
mkWeakMap.get([obj]); // => 'foo'
Name | Type |
---|---|
keys |
readonly K [] |
value |
V |
MKWeakMap
<K
, V
>
Name | Type |
---|---|
K |
extends object |
• new MKWeakSet<K
>(iterable?
)
Creates a new MKWeakSet object.
Could be called with initial keys
const empty = new MKWeakSet();
const withValues = new MKWeakSet([
[{foo: 'bar'}]
]);
Name | Type |
---|---|
K |
extends object |
Name | Type |
---|---|
iterable? |
Iterable <readonly K []> |
▸ add(keys
): void
Add keys to the MKWeakSet object.
const mkWeakSet = new MKWeakSet();
const obj = {};
mkWeakSet.add([obj]);
mkWeakSet.has([obj]); // => 'true'
Name | Type |
---|---|
keys |
readonly K [] |
void
▸ delete(keys
): boolean
Removes keys from the MKWeakSet. Returns true if keys has been removed successfully.
const obj = {};
const mkWeakSet = new MKWeakSet([[obj]]);
mkWeakSet.delete([obj]); // => true
mkWeakSet.delete([obj]); // => false
Name | Type |
---|---|
keys |
readonly K [] |
boolean
▸ has(keys
): boolean
Returns true if an element with the specified keys exists in the MKWeakSet object.
const obj = {};
const mkWeakSet = new MKWeakSet([[obj]]);
mkWeakSet.has([obj]); // => 'true'
Name | Type |
---|---|
keys |
readonly K [] |
boolean