heap-typed
Advanced tools
Comparing version 1.46.3 to 1.46.5
@@ -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<object, 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) => object; | ||
/** | ||
* 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,47 @@ } | ||
* 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); | ||
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 +153,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 +197,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 +263,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 +285,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 +311,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,6 +18,2 @@ "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); |
@@ -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) => object; | ||
}; |
@@ -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,7 +17,3 @@ "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); |
@@ -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 object; | ||
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,8 +84,8 @@ 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; |
{ | ||
"name": "heap-typed", | ||
"version": "1.46.3", | ||
"version": "1.46.5", | ||
"description": "Heap. Javascript & Typescript Data Structure.", | ||
@@ -134,4 +134,4 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"data-structure-typed": "^1.46.3" | ||
"data-structure-typed": "^1.46.5" | ||
} | ||
} |
@@ -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<object, 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) => object; | ||
/** | ||
* 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) => (<object>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,49 @@ | ||
* 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); | ||
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 +170,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 +215,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 +289,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 +313,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 +365,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) => object | ||
} |
@@ -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 object => { | ||
const inputType = typeof input; | ||
@@ -99,0 +99,0 @@ return (inputType === 'object' && input !== null) || inputType === 'function'; |
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
1797496
344
33111
Updateddata-structure-typed@^1.46.5