data-structure-typed
Advanced tools
Comparing version 1.46.3 to 1.46.4
@@ -6,4 +6,4 @@ { | ||
"test name": "1,000,000 set", | ||
"time taken (ms)": "172.42", | ||
"executions per sec": "5.80", | ||
"time taken (ms)": "217.67", | ||
"executions per sec": "4.59", | ||
"sample deviation": "0.02" | ||
@@ -13,17 +13,5 @@ }, | ||
"test name": "1,000,000 CPT set", | ||
"time taken (ms)": "172.27", | ||
"executions per sec": "5.80", | ||
"sample deviation": "0.02" | ||
}, | ||
{ | ||
"test name": "1,000,000 set & get", | ||
"time taken (ms)": "182.19", | ||
"executions per sec": "5.49", | ||
"sample deviation": "0.02" | ||
}, | ||
{ | ||
"test name": "1,000,000 CPT set & get", | ||
"time taken (ms)": "175.65", | ||
"executions per sec": "5.69", | ||
"sample deviation": "0.02" | ||
"time taken (ms)": "176.11", | ||
"executions per sec": "5.68", | ||
"sample deviation": "0.03" | ||
} | ||
@@ -30,0 +18,0 @@ ], |
@@ -11,3 +11,3 @@ # Changelog | ||
## [v1.46.3](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) | ||
## [v1.46.4](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) | ||
@@ -14,0 +14,0 @@ ### Changes |
@@ -8,17 +8,17 @@ /** | ||
*/ | ||
import { HashMapLinkedNode, IterableWithSizeOrLength } from '../../types'; | ||
import { HashMapLinkedNode, HashMapOptions } from '../../types'; | ||
export declare class HashMap<K = any, V = any> { | ||
readonly OBJ_KEY_INDEX: symbol; | ||
protected _nodes: HashMapLinkedNode<K, V>[]; | ||
protected _orgMap: Record<string, HashMapLinkedNode<K, V>>; | ||
protected _head: HashMapLinkedNode<K, V>; | ||
protected _tail: HashMapLinkedNode<K, V>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>>; | ||
protected _objMap: WeakMap<WeakKey, HashMapLinkedNode<K, V | undefined>>; | ||
protected _head: HashMapLinkedNode<K, V | undefined>; | ||
protected _tail: HashMapLinkedNode<K, V | undefined>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>; | ||
protected _hashFn: (key: K) => string; | ||
protected _objHashFn: (key: K) => WeakKey; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param {Iterable<[K, V]>} elements - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs. | ||
* @param options - The `options` parameter is an object that contains the `elements` property. The | ||
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`. | ||
*/ | ||
constructor(elements?: IterableWithSizeOrLength<[K, V]>); | ||
constructor(options?: HashMapOptions<K, V>); | ||
protected _size: number; | ||
@@ -47,3 +47,3 @@ get size(): number; | ||
*/ | ||
begin(): Generator<(K | V)[], void, unknown>; | ||
begin(): Generator<(K | V | undefined)[], void, unknown>; | ||
/** | ||
@@ -53,3 +53,3 @@ * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's | ||
*/ | ||
reverseBegin(): Generator<(K | V)[], void, unknown>; | ||
reverseBegin(): Generator<(K | V | undefined)[], void, unknown>; | ||
/** | ||
@@ -65,6 +65,5 @@ * Time Complexity: O(1) | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key: K, value?: V, isObjectKey?: boolean): number; | ||
set(key: K, value?: V): number; | ||
/** | ||
@@ -78,11 +77,8 @@ * Time Complexity: O(1) | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key: K, isObjectKey?: boolean): V | undefined; | ||
get(key: K): V | undefined; | ||
/** | ||
@@ -107,9 +103,6 @@ * Time Complexity: O(n), where n is the index. | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key: K, isObjectKey?: boolean): boolean; | ||
delete(key: K): boolean; | ||
/** | ||
@@ -151,2 +144,5 @@ * Time Complexity: O(n), where n is the index. | ||
forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void): void; | ||
filter(predicate: (element: [K, V], map: HashMap<K, V>) => boolean): HashMap<K, V>; | ||
map<NV>(callback: (element: [K, V], map: HashMap<K, V>) => NV): HashMap<K, NV>; | ||
reduce<A>(callback: (accumulator: A, element: [K, V], map: HashMap<K, V>) => A, initialValue: A): A; | ||
/** | ||
@@ -169,3 +165,3 @@ * Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
*/ | ||
protected _deleteNode(node: HashMapLinkedNode<K, V>): void; | ||
protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): void; | ||
} |
@@ -14,17 +14,23 @@ "use strict"; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param {Iterable<[K, V]>} elements - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs. | ||
* @param options - The `options` parameter is an object that contains the `elements` property. The | ||
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`. | ||
*/ | ||
constructor(elements = []) { | ||
this.OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX'); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
constructor(options = { | ||
elements: [], | ||
hashFn: (key) => String(key), | ||
objHashFn: (key) => key | ||
}) { | ||
this._noObjMap = {}; | ||
this._objMap = new WeakMap(); | ||
this._size = 0; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._sentinel = {}; | ||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel; | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
const { elements, hashFn, objHashFn } = options; | ||
this._hashFn = hashFn; | ||
this._objHashFn = objHashFn; | ||
if (elements) { | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
} | ||
} | ||
@@ -92,48 +98,48 @@ } | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key, value, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
let newTail; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index !== undefined) { | ||
this._nodes[index].value = value; | ||
return this._size; | ||
set(key, value) { | ||
let node; | ||
if ((0, utils_1.isWeakKey)(key)) { | ||
// const hash = this._objHashFn(key); | ||
const hash = key; | ||
node = this._objMap.get(hash); | ||
if (node) { | ||
// If the node already exists, update its value | ||
node.value = value; | ||
} | ||
Object.defineProperty(key, this.OBJ_KEY_INDEX, { | ||
value: this._nodes.length, | ||
configurable: true | ||
}); | ||
newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
this._nodes.push(newTail); | ||
else { | ||
// Create new node | ||
node = { key: hash, value, prev: this._tail, next: this._sentinel }; | ||
// Add new nodes to _objMap and linked list | ||
this._objMap.set(hash, node); | ||
} | ||
} | ||
else { | ||
const node = this._orgMap[key]; | ||
const hash = this._hashFn(key); | ||
// Non-object keys are handled in the same way as the original implementation | ||
node = this._noObjMap[hash]; | ||
if (node) { | ||
node.value = value; | ||
return this._size; | ||
} | ||
this._orgMap[key] = newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
else { | ||
this._noObjMap[hash] = node = { | ||
key, | ||
value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
} | ||
if (this._size === 0) { | ||
this._head = newTail; | ||
this._sentinel.next = newTail; | ||
this._head = node; | ||
this._sentinel.next = node; | ||
} | ||
else { | ||
this._tail.next = newTail; | ||
this._tail.next = node; | ||
} | ||
this._tail = newTail; | ||
this._sentinel.prev = newTail; | ||
return ++this._size; | ||
this._tail = node; | ||
this._sentinel.prev = node; | ||
this._size++; | ||
return this._size; | ||
} | ||
@@ -148,17 +154,18 @@ /** | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
return index !== undefined ? this._nodes[index].value : undefined; | ||
get(key) { | ||
if ((0, utils_1.isWeakKey)(key)) { | ||
const hash = this._objHashFn(key); | ||
const node = this._objMap.get(hash); | ||
return node ? node.value : undefined; | ||
} | ||
const node = this._orgMap[key]; | ||
return node ? node.value : undefined; | ||
else { | ||
const hash = this._hashFn(key); | ||
const node = this._noObjMap[hash]; | ||
return node ? node.value : undefined; | ||
} | ||
} | ||
@@ -191,24 +198,28 @@ /** | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
delete(key) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) | ||
return false; | ||
delete key[this.OBJ_KEY_INDEX]; | ||
node = this._nodes[index]; | ||
delete this._nodes[index]; | ||
if ((0, utils_1.isWeakKey)(key)) { | ||
const hash = this._objHashFn(key); | ||
// Get nodes from WeakMap | ||
node = this._objMap.get(hash); | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from WeakMap | ||
this._objMap.delete(hash); | ||
} | ||
else { | ||
node = this._orgMap[key]; | ||
if (node === undefined) | ||
return false; | ||
delete this._orgMap[key]; | ||
const hash = this._hashFn(key); | ||
// Get nodes from noObjMap | ||
node = this._noObjMap[hash]; | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from orgMap | ||
delete this._noObjMap[hash]; | ||
} | ||
// Remove node from doubly linked list | ||
this._deleteNode(node); | ||
@@ -253,9 +264,3 @@ return true; | ||
clear() { | ||
// const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX; | ||
// this._nodes.forEach(el => { | ||
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX]; | ||
// }); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._noObjMap = {}; | ||
this._size = 0; | ||
@@ -281,2 +286,26 @@ this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel; | ||
} | ||
filter(predicate) { | ||
const filteredMap = new HashMap(); | ||
for (const [key, value] of this) { | ||
if (predicate([key, value], this)) { | ||
filteredMap.set(key, value); | ||
} | ||
} | ||
return filteredMap; | ||
} | ||
map(callback) { | ||
const mappedMap = new HashMap(); | ||
for (const [key, value] of this) { | ||
const newValue = callback([key, value], this); | ||
mappedMap.set(key, newValue); | ||
} | ||
return mappedMap; | ||
} | ||
reduce(callback, initialValue) { | ||
let accumulator = initialValue; | ||
for (const element of this) { | ||
accumulator = callback(accumulator, element, this); | ||
} | ||
return accumulator; | ||
} | ||
/** | ||
@@ -283,0 +312,0 @@ * Time Complexity: O(n), where n is the number of elements in the HashMap. |
export * from './hash-table'; | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export * from './hash-map'; |
@@ -18,7 +18,3 @@ "use strict"; | ||
__exportStar(require("./hash-table"), exports); | ||
__exportStar(require("./coordinate-map"), exports); | ||
__exportStar(require("./coordinate-set"), exports); | ||
__exportStar(require("./tree-map"), exports); | ||
__exportStar(require("./tree-set"), exports); | ||
__exportStar(require("./hash-map"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -7,1 +7,6 @@ export type HashMapLinkedNode<K, V> = { | ||
}; | ||
export type HashMapOptions<K, V> = { | ||
elements: Iterable<[K, V]>; | ||
hashFn: (key: K) => string; | ||
objHashFn: (key: K) => WeakKey; | ||
}; |
@@ -1,7 +0,3 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export type HashFunction<K> = (key: K) => number; |
@@ -17,8 +17,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./coordinate-map"), exports); | ||
__exportStar(require("./coordinate-set"), exports); | ||
__exportStar(require("./hash-map"), exports); | ||
__exportStar(require("./hash-table"), exports); | ||
__exportStar(require("./tree-map"), exports); | ||
__exportStar(require("./tree-set"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -23,3 +23,3 @@ /** | ||
export declare const throwRangeError: (message?: string) => void; | ||
export declare const isObjOrFunc: (input: unknown) => input is Record<string, unknown> | ((...args: any[]) => any); | ||
export declare const isWeakKey: (input: unknown) => input is WeakKey; | ||
export declare const calcMinUnitsRequired: (totalQuantity: number, unitSize: number) => number; |
@@ -12,3 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.calcMinUnitsRequired = exports.isObjOrFunc = exports.throwRangeError = exports.rangeCheck = exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0; | ||
exports.calcMinUnitsRequired = exports.isWeakKey = exports.throwRangeError = exports.rangeCheck = exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0; | ||
const uuidV4 = function () { | ||
@@ -84,9 +84,9 @@ return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) { | ||
exports.throwRangeError = throwRangeError; | ||
const isObjOrFunc = (input) => { | ||
const isWeakKey = (input) => { | ||
const inputType = typeof input; | ||
return (inputType === 'object' && input !== null) || inputType === 'function'; | ||
}; | ||
exports.isObjOrFunc = isObjOrFunc; | ||
exports.isWeakKey = isWeakKey; | ||
const calcMinUnitsRequired = (totalQuantity, unitSize) => Math.floor((totalQuantity + unitSize - 1) / unitSize); | ||
exports.calcMinUnitsRequired = calcMinUnitsRequired; | ||
//# sourceMappingURL=utils.js.map |
@@ -8,17 +8,17 @@ /** | ||
*/ | ||
import { HashMapLinkedNode, IterableWithSizeOrLength } from '../../types'; | ||
import { HashMapLinkedNode, HashMapOptions } from '../../types'; | ||
export declare class HashMap<K = any, V = any> { | ||
readonly OBJ_KEY_INDEX: symbol; | ||
protected _nodes: HashMapLinkedNode<K, V>[]; | ||
protected _orgMap: Record<string, HashMapLinkedNode<K, V>>; | ||
protected _head: HashMapLinkedNode<K, V>; | ||
protected _tail: HashMapLinkedNode<K, V>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>>; | ||
protected _objMap: WeakMap<WeakKey, HashMapLinkedNode<K, V | undefined>>; | ||
protected _head: HashMapLinkedNode<K, V | undefined>; | ||
protected _tail: HashMapLinkedNode<K, V | undefined>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>; | ||
protected _hashFn: (key: K) => string; | ||
protected _objHashFn: (key: K) => WeakKey; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param {Iterable<[K, V]>} elements - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs. | ||
* @param options - The `options` parameter is an object that contains the `elements` property. The | ||
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`. | ||
*/ | ||
constructor(elements?: IterableWithSizeOrLength<[K, V]>); | ||
constructor(options?: HashMapOptions<K, V>); | ||
protected _size: number; | ||
@@ -47,3 +47,3 @@ get size(): number; | ||
*/ | ||
begin(): Generator<(K | V)[], void, unknown>; | ||
begin(): Generator<(K | V | undefined)[], void, unknown>; | ||
/** | ||
@@ -53,3 +53,3 @@ * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's | ||
*/ | ||
reverseBegin(): Generator<(K | V)[], void, unknown>; | ||
reverseBegin(): Generator<(K | V | undefined)[], void, unknown>; | ||
/** | ||
@@ -65,6 +65,5 @@ * Time Complexity: O(1) | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key: K, value?: V, isObjectKey?: boolean): number; | ||
set(key: K, value?: V): number; | ||
/** | ||
@@ -78,11 +77,8 @@ * Time Complexity: O(1) | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key: K, isObjectKey?: boolean): V | undefined; | ||
get(key: K): V | undefined; | ||
/** | ||
@@ -107,9 +103,6 @@ * Time Complexity: O(n), where n is the index. | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key: K, isObjectKey?: boolean): boolean; | ||
delete(key: K): boolean; | ||
/** | ||
@@ -151,2 +144,5 @@ * Time Complexity: O(n), where n is the index. | ||
forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void): void; | ||
filter(predicate: (element: [K, V], map: HashMap<K, V>) => boolean): HashMap<K, V>; | ||
map<NV>(callback: (element: [K, V], map: HashMap<K, V>) => NV): HashMap<K, NV>; | ||
reduce<A>(callback: (accumulator: A, element: [K, V], map: HashMap<K, V>) => A, initialValue: A): A; | ||
/** | ||
@@ -169,3 +165,3 @@ * Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
*/ | ||
protected _deleteNode(node: HashMapLinkedNode<K, V>): void; | ||
protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): void; | ||
} |
@@ -8,22 +8,30 @@ /** | ||
*/ | ||
import { isObjOrFunc, rangeCheck } from '../../utils'; | ||
import { isWeakKey, rangeCheck } from '../../utils'; | ||
export class HashMap { | ||
OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX'); | ||
_nodes = []; | ||
_orgMap = {}; | ||
_noObjMap = {}; | ||
_objMap = new WeakMap(); | ||
_head; | ||
_tail; | ||
_sentinel; | ||
_hashFn; | ||
_objHashFn; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param {Iterable<[K, V]>} elements - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs. | ||
* @param options - The `options` parameter is an object that contains the `elements` property. The | ||
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`. | ||
*/ | ||
constructor(elements = []) { | ||
Object.setPrototypeOf(this._orgMap, null); | ||
constructor(options = { | ||
elements: [], | ||
hashFn: (key) => String(key), | ||
objHashFn: (key) => key | ||
}) { | ||
this._sentinel = {}; | ||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel; | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
const { elements, hashFn, objHashFn } = options; | ||
this._hashFn = hashFn; | ||
this._objHashFn = objHashFn; | ||
if (elements) { | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
} | ||
} | ||
@@ -92,48 +100,48 @@ } | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key, value, isObjectKey = isObjOrFunc(key)) { | ||
let newTail; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index !== undefined) { | ||
this._nodes[index].value = value; | ||
return this._size; | ||
set(key, value) { | ||
let node; | ||
if (isWeakKey(key)) { | ||
// const hash = this._objHashFn(key); | ||
const hash = key; | ||
node = this._objMap.get(hash); | ||
if (node) { | ||
// If the node already exists, update its value | ||
node.value = value; | ||
} | ||
Object.defineProperty(key, this.OBJ_KEY_INDEX, { | ||
value: this._nodes.length, | ||
configurable: true | ||
}); | ||
newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
this._nodes.push(newTail); | ||
else { | ||
// Create new node | ||
node = { key: hash, value, prev: this._tail, next: this._sentinel }; | ||
// Add new nodes to _objMap and linked list | ||
this._objMap.set(hash, node); | ||
} | ||
} | ||
else { | ||
const node = this._orgMap[key]; | ||
const hash = this._hashFn(key); | ||
// Non-object keys are handled in the same way as the original implementation | ||
node = this._noObjMap[hash]; | ||
if (node) { | ||
node.value = value; | ||
return this._size; | ||
} | ||
this._orgMap[key] = newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
else { | ||
this._noObjMap[hash] = node = { | ||
key, | ||
value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
} | ||
if (this._size === 0) { | ||
this._head = newTail; | ||
this._sentinel.next = newTail; | ||
this._head = node; | ||
this._sentinel.next = node; | ||
} | ||
else { | ||
this._tail.next = newTail; | ||
this._tail.next = node; | ||
} | ||
this._tail = newTail; | ||
this._sentinel.prev = newTail; | ||
return ++this._size; | ||
this._tail = node; | ||
this._sentinel.prev = node; | ||
this._size++; | ||
return this._size; | ||
} | ||
@@ -148,17 +156,18 @@ /** | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key, isObjectKey = isObjOrFunc(key)) { | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
return index !== undefined ? this._nodes[index].value : undefined; | ||
get(key) { | ||
if (isWeakKey(key)) { | ||
const hash = this._objHashFn(key); | ||
const node = this._objMap.get(hash); | ||
return node ? node.value : undefined; | ||
} | ||
const node = this._orgMap[key]; | ||
return node ? node.value : undefined; | ||
else { | ||
const hash = this._hashFn(key); | ||
const node = this._noObjMap[hash]; | ||
return node ? node.value : undefined; | ||
} | ||
} | ||
@@ -191,24 +200,28 @@ /** | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key, isObjectKey = isObjOrFunc(key)) { | ||
delete(key) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) | ||
return false; | ||
delete key[this.OBJ_KEY_INDEX]; | ||
node = this._nodes[index]; | ||
delete this._nodes[index]; | ||
if (isWeakKey(key)) { | ||
const hash = this._objHashFn(key); | ||
// Get nodes from WeakMap | ||
node = this._objMap.get(hash); | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from WeakMap | ||
this._objMap.delete(hash); | ||
} | ||
else { | ||
node = this._orgMap[key]; | ||
if (node === undefined) | ||
return false; | ||
delete this._orgMap[key]; | ||
const hash = this._hashFn(key); | ||
// Get nodes from noObjMap | ||
node = this._noObjMap[hash]; | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from orgMap | ||
delete this._noObjMap[hash]; | ||
} | ||
// Remove node from doubly linked list | ||
this._deleteNode(node); | ||
@@ -253,9 +266,3 @@ return true; | ||
clear() { | ||
// const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX; | ||
// this._nodes.forEach(el => { | ||
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX]; | ||
// }); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._noObjMap = {}; | ||
this._size = 0; | ||
@@ -281,2 +288,26 @@ this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel; | ||
} | ||
filter(predicate) { | ||
const filteredMap = new HashMap(); | ||
for (const [key, value] of this) { | ||
if (predicate([key, value], this)) { | ||
filteredMap.set(key, value); | ||
} | ||
} | ||
return filteredMap; | ||
} | ||
map(callback) { | ||
const mappedMap = new HashMap(); | ||
for (const [key, value] of this) { | ||
const newValue = callback([key, value], this); | ||
mappedMap.set(key, newValue); | ||
} | ||
return mappedMap; | ||
} | ||
reduce(callback, initialValue) { | ||
let accumulator = initialValue; | ||
for (const element of this) { | ||
accumulator = callback(accumulator, element, this); | ||
} | ||
return accumulator; | ||
} | ||
/** | ||
@@ -283,0 +314,0 @@ * Time Complexity: O(n), where n is the number of elements in the HashMap. |
export * from './hash-table'; | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export * from './hash-map'; |
export * from './hash-table'; | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export * from './hash-map'; |
@@ -7,1 +7,6 @@ export type HashMapLinkedNode<K, V> = { | ||
}; | ||
export type HashMapOptions<K, V> = { | ||
elements: Iterable<[K, V]>; | ||
hashFn: (key: K) => string; | ||
objHashFn: (key: K) => WeakKey; | ||
}; |
@@ -1,7 +0,3 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export type HashFunction<K> = (key: K) => number; |
@@ -1,6 +0,2 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; |
@@ -23,3 +23,3 @@ /** | ||
export declare const throwRangeError: (message?: string) => void; | ||
export declare const isObjOrFunc: (input: unknown) => input is Record<string, unknown> | ((...args: any[]) => any); | ||
export declare const isWeakKey: (input: unknown) => input is WeakKey; | ||
export declare const calcMinUnitsRequired: (totalQuantity: number, unitSize: number) => number; |
@@ -62,3 +62,3 @@ export const uuidV4 = function () { | ||
}; | ||
export const isObjOrFunc = (input) => { | ||
export const isWeakKey = (input) => { | ||
const inputType = typeof input; | ||
@@ -65,0 +65,0 @@ return (inputType === 'object' && input !== null) || inputType === 'function'; |
{ | ||
"name": "data-structure-typed", | ||
"version": "1.46.3", | ||
"version": "1.46.4", | ||
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.", | ||
@@ -5,0 +5,0 @@ "main": "dist/cjs/index.js", |
@@ -9,27 +9,37 @@ /** | ||
import { isObjOrFunc, rangeCheck } from '../../utils'; | ||
import { HashMapLinkedNode, IterableWithSizeOrLength } from '../../types'; | ||
import { isWeakKey, rangeCheck } from '../../utils'; | ||
import { HashMapLinkedNode, HashMapOptions } from '../../types'; | ||
export class HashMap<K = any, V = any> { | ||
readonly OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX'); | ||
protected _nodes: HashMapLinkedNode<K, V>[] = []; | ||
protected _orgMap: Record<string, HashMapLinkedNode<K, V>> = {}; | ||
protected _head: HashMapLinkedNode<K, V>; | ||
protected _tail: HashMapLinkedNode<K, V>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {}; | ||
protected _objMap = new WeakMap<WeakKey, HashMapLinkedNode<K, V | undefined>>(); | ||
protected _head: HashMapLinkedNode<K, V | undefined>; | ||
protected _tail: HashMapLinkedNode<K, V | undefined>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>; | ||
protected _hashFn: (key: K) => string; | ||
protected _objHashFn: (key: K) => WeakKey; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param {Iterable<[K, V]>} elements - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs. | ||
* @param options - The `options` parameter is an object that contains the `elements` property. The | ||
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`. | ||
*/ | ||
constructor(elements: IterableWithSizeOrLength<[K, V]> = []) { | ||
Object.setPrototypeOf(this._orgMap, null); | ||
constructor(options: HashMapOptions<K, V> = { | ||
elements: [], | ||
hashFn: (key: K) => String(key), | ||
objHashFn: (key: K) => (<WeakKey>key) | ||
}) { | ||
this._sentinel = <HashMapLinkedNode<K, V>>{}; | ||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel; | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
const { elements, hashFn, objHashFn } = options; | ||
this._hashFn = hashFn; | ||
this._objHashFn = objHashFn; | ||
if (elements) { | ||
for (const el of elements) { | ||
this.set(el[0], el[1]); | ||
} | ||
} | ||
} | ||
@@ -102,46 +112,50 @@ | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key: K, value?: V, isObjectKey: boolean = isObjOrFunc(key)) { | ||
let newTail; | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX]; | ||
if (index !== undefined) { | ||
this._nodes[<number>index].value = <V>value; | ||
return this._size; | ||
set(key: K, value?: V) { | ||
let node; | ||
if (isWeakKey(key)) { | ||
// const hash = this._objHashFn(key); | ||
const hash = key; | ||
node = this._objMap.get(hash); | ||
if (node) { | ||
// If the node already exists, update its value | ||
node.value = value; | ||
} else { | ||
// Create new node | ||
node = { key: <K>hash, value, prev: this._tail, next: this._sentinel }; | ||
// Add new nodes to _objMap and linked list | ||
this._objMap.set(hash, node); | ||
} | ||
Object.defineProperty(key, this.OBJ_KEY_INDEX, { | ||
value: this._nodes.length, | ||
configurable: true | ||
}); | ||
newTail = { | ||
key: key, | ||
value: <V>value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
this._nodes.push(newTail); | ||
} else { | ||
const node = this._orgMap[<string>(<unknown>key)]; | ||
const hash = this._hashFn(key); | ||
// Non-object keys are handled in the same way as the original implementation | ||
node = this._noObjMap[hash]; | ||
if (node) { | ||
node.value = <V>value; | ||
return this._size; | ||
node.value = value; | ||
} else { | ||
this._noObjMap[hash] = node = { | ||
key, | ||
value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
this._orgMap[<string>(<unknown>key)] = newTail = { | ||
key: key, | ||
value: <V>value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
if (this._size === 0) { | ||
this._head = newTail; | ||
this._sentinel.next = newTail; | ||
this._head = node; | ||
this._sentinel.next = node; | ||
} else { | ||
this._tail.next = newTail; | ||
this._tail.next = node; | ||
} | ||
this._tail = newTail; | ||
this._sentinel.prev = newTail; | ||
return ++this._size; | ||
this._tail = node; | ||
this._sentinel.prev = node; | ||
this._size++; | ||
return this._size; | ||
} | ||
@@ -157,17 +171,17 @@ | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key: K, isObjectKey: boolean = isObjOrFunc(key)) { | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX]; | ||
return index !== undefined ? this._nodes[index].value : undefined; | ||
get(key: K): V | undefined { | ||
if (isWeakKey(key)) { | ||
const hash = this._objHashFn(key); | ||
const node = this._objMap.get(hash); | ||
return node ? node.value : undefined; | ||
} else { | ||
const hash = this._hashFn(key); | ||
const node = this._noObjMap[hash]; | ||
return node ? node.value : undefined; | ||
} | ||
const node = this._orgMap[<string>(<unknown>key)]; | ||
return node ? node.value : undefined; | ||
} | ||
@@ -202,21 +216,33 @@ | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key: K, isObjectKey: boolean = isObjOrFunc(key)) { | ||
delete(key: K) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) return false; | ||
delete (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX]; | ||
node = this._nodes[index]; | ||
delete this._nodes[index]; | ||
if (isWeakKey(key)) { | ||
const hash = this._objHashFn(key); | ||
// Get nodes from WeakMap | ||
node = this._objMap.get(hash); | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from WeakMap | ||
this._objMap.delete(hash); | ||
} else { | ||
node = this._orgMap[<string>(<unknown>key)]; | ||
if (node === undefined) return false; | ||
delete this._orgMap[<string>(<unknown>key)]; | ||
const hash = this._hashFn(key); | ||
// Get nodes from noObjMap | ||
node = this._noObjMap[hash]; | ||
if (!node) { | ||
return false; // If the node does not exist, return false | ||
} | ||
// Remove nodes from orgMap | ||
delete this._noObjMap[hash]; | ||
} | ||
// Remove node from doubly linked list | ||
this._deleteNode(node); | ||
@@ -264,9 +290,3 @@ return true; | ||
clear() { | ||
// const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX; | ||
// this._nodes.forEach(el => { | ||
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX]; | ||
// }); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._noObjMap = {}; | ||
this._size = 0; | ||
@@ -294,2 +314,29 @@ this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel; | ||
filter(predicate: (element: [K, V], map: HashMap<K, V>) => boolean): HashMap<K, V> { | ||
const filteredMap = new HashMap<K, V>(); | ||
for (const [key, value] of this) { | ||
if (predicate([key, value], this)) { | ||
filteredMap.set(key, value); | ||
} | ||
} | ||
return filteredMap; | ||
} | ||
map<NV>(callback: (element: [K, V], map: HashMap<K, V>) => NV): HashMap<K, NV> { | ||
const mappedMap = new HashMap<K, NV>(); | ||
for (const [key, value] of this) { | ||
const newValue = callback([key, value], this); | ||
mappedMap.set(key, newValue); | ||
} | ||
return mappedMap; | ||
} | ||
reduce<A>(callback: (accumulator: A, element: [K, V], map: HashMap<K, V>) => A, initialValue: A): A { | ||
let accumulator = initialValue; | ||
for (const element of this) { | ||
accumulator = callback(accumulator, element, this); | ||
} | ||
return accumulator; | ||
} | ||
/** | ||
@@ -319,14 +366,17 @@ * Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
*/ | ||
protected _deleteNode(node: HashMapLinkedNode<K, V>) { | ||
protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>) { | ||
const { prev, next } = node; | ||
prev.next = next; | ||
next.prev = prev; | ||
if (node === this._head) { | ||
this._head = next; | ||
} | ||
if (node === this._tail) { | ||
this._tail = prev; | ||
} | ||
this._size -= 1; | ||
} | ||
} |
export * from './hash-table'; | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export * from './hash-map'; |
@@ -7,1 +7,7 @@ export type HashMapLinkedNode<K, V> = { | ||
}; | ||
export type HashMapOptions<K, V> = { | ||
elements: Iterable<[K, V]>; | ||
hashFn: (key: K) => string; | ||
objHashFn: (key: K) => WeakKey | ||
} |
@@ -1,8 +0,4 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export type HashFunction<K> = (key: K) => number; |
@@ -96,3 +96,3 @@ /** | ||
export const isObjOrFunc = (input: unknown): input is Record<string, unknown> | ((...args: any[]) => any) => { | ||
export const isWeakKey = (input: unknown): input is WeakKey => { | ||
const inputType = typeof input; | ||
@@ -99,0 +99,0 @@ return (inputType === 'object' && input !== null) || inputType === 'function'; |
@@ -17,2 +17,3 @@ import { HashMap } from '../../../../src'; | ||
}); | ||
if (isCompetitor) { | ||
@@ -27,2 +28,15 @@ suite.add(`${MILLION.toLocaleString()} CPT set`, () => { | ||
} | ||
suite.add(`${MILLION.toLocaleString()} Map set`, () => { | ||
const hm = new Map<number, number>(); | ||
for (let i = 0; i < MILLION; i++) hm.set(i, i); | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} Set add`, () => { | ||
const hs = new Set<number>(); | ||
for (let i = 0; i < MILLION; i++) hs.add(i); | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} set & get`, () => { | ||
@@ -38,2 +52,3 @@ const hm = new HashMap<number, number>(); | ||
}); | ||
if (isCompetitor) { | ||
@@ -51,2 +66,62 @@ suite.add(`${MILLION.toLocaleString()} CPT set & get`, () => { | ||
} | ||
suite.add(`${MILLION.toLocaleString()} Map set & get`, () => { | ||
const hm = new Map<number, number>(); | ||
for (let i = 0; i < MILLION; i++) { | ||
hm.set(i, i); | ||
} | ||
for (let i = 0; i < MILLION; i++) { | ||
hm.get(i); | ||
} | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} Set add & has`, () => { | ||
const hs = new Set<number>(); | ||
for (let i = 0; i < MILLION; i++) hs.add(i); | ||
for (let i = 0; i < MILLION; i++) hs.has(i); | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} ObjKey set & get`, () => { | ||
const hm = new HashMap<[number, number], number>(); | ||
const objKeys:[number, number][] = []; | ||
for (let i = 0; i < MILLION; i++) { | ||
const obj: [number, number] = [i, i]; | ||
objKeys.push(obj) | ||
hm.set(obj, i); | ||
} | ||
for (let i = 0; i < MILLION; i++) { | ||
hm.get(objKeys[i]); | ||
} | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} Map ObjKey set & get`, () => { | ||
const hm = new Map<[number, number], number>(); | ||
const objs:[number, number][] = []; | ||
for (let i = 0; i < MILLION; i++) { | ||
const obj: [number, number] = [i, i]; | ||
objs.push(obj) | ||
hm.set(obj, i); | ||
} | ||
for (let i = 0; i < MILLION; i++) { | ||
hm.get(objs[i]); | ||
} | ||
}); | ||
suite.add(`${MILLION.toLocaleString()} Set ObjKey add & has`, () => { | ||
const hs = new Set<[number, number]>(); | ||
const objs:[number, number][] = []; | ||
for (let i = 0; i < MILLION; i++) { | ||
const obj: [number, number] = [i, i]; | ||
objs.push(obj) | ||
hs.add(obj); | ||
} | ||
for (let i = 0; i < MILLION; i++) { | ||
hs.has(objs[i]); | ||
} | ||
}); | ||
export { suite }; |
@@ -232,1 +232,33 @@ import { HashMap } from '../../../../src'; | ||
}); | ||
describe('HashMap for coordinate object keys', () => { | ||
const hashMap: HashMap<[number, number], number> = new HashMap(); | ||
const codObjs: [number, number][] = []; | ||
test('set elements in hash map', () => { | ||
for (let i = 0; i < 1000; i++) { | ||
const codObj: [number, number] = [getRandomInt(-10000, 10000), i]; | ||
codObjs.push(codObj); | ||
hashMap.set(codObj, i); | ||
} | ||
}); | ||
test('get elements in hash map', () => { | ||
for (let i = 0; i < 1000; i++) { | ||
const codObj = codObjs[i]; | ||
if (codObj) { | ||
expect(hashMap.get(codObj)).toBe(i); | ||
} | ||
} | ||
}); | ||
test('delete elements in hash map', () => { | ||
for (let i = 0; i < 1000; i++) { | ||
if (i === 500) expect(hashMap.size).toBe(500) | ||
const codObj = codObjs[i]; | ||
if (codObj) hashMap.delete(codObj); | ||
} | ||
expect(hashMap.size).toBe(0); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
123
3982896
738
75528