UNPKG

deque-typed

Version:
429 lines (428 loc) 15.5 kB
/** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com> * @license MIT License */ import type { EntryCallback, HashMapLinkedNode, HashMapOptions, HashMapStoreItem, LinkedHashMapOptions } from '../../types'; import { IterableEntryBase } from '../base'; /** * Hash-based map. Supports object keys and custom hashing; offers O(1) average set/get/has. * @remarks Time O(1), Space O(1) * @template K * @template V * @template R * 1. Key-Value Pair Storage: HashMap stores key-value pairs. Each key map to a value. * 2. Fast Lookup: It's used when you need to quickly find, insert, or delete entries based on a key. * 3. Unique Keys: Keys are unique. * If you try to insert another entry with the same key, the new one will replace the old entry. * 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time. * @example * // should maintain insertion order * const linkedHashMap = new LinkedHashMap<number, string>(); * linkedHashMap.set(1, 'A'); * linkedHashMap.set(2, 'B'); * linkedHashMap.set(3, 'C'); * * const result = Array.from(linkedHashMap); * console.log(result); // [ * // [1, 'A'], * // [2, 'B'], * // [3, 'C'] * // ]; * @example * // basic HashMap creation and set operation * // Create a simple HashMap with key-value pairs * const map = new HashMap<number, string>([ * [1, 'one'], * [2, 'two'], * [3, 'three'] * ]); * * // Verify size * console.log(map.size); // 3; * * // Set a new key-value pair * map.set(4, 'four'); * console.log(map.size); // 4; * * // Verify entries * console.log([...map.entries()]); // length: 4; * @example * // HashMap get and has operations * const map = new HashMap<string, number>([ * ['apple', 1], * ['banana', 2], * ['cherry', 3] * ]); * * // Check if key exists * console.log(map.has('apple')); // true; * console.log(map.has('date')); // false; * * // Get value by key * console.log(map.get('banana')); // 2; * console.log(map.get('grape')); // undefined; * * // Get all keys and values * const keys = [...map.keys()]; * const values = [...map.values()]; * console.log(keys); // contains 'apple'; * console.log(values); // contains 3; * @example * // HashMap iteration and filter operations * const map = new HashMap<number, string>([ * [1, 'Alice'], * [2, 'Bob'], * [3, 'Charlie'], * [4, 'Diana'], * [5, 'Eve'] * ]); * * // Iterate through entries * const entries: [number, string][] = []; * for (const [key, value] of map) { * entries.push([key, value]); * } * console.log(entries); // length: 5; * * // Filter operation (for iteration with collection methods) * const filtered = [...map].filter(([key]) => key > 2); * console.log(filtered.length); // 3; * * // Map operation * const values = [...map.values()].map(v => v.length); * console.log(values); // contains 3; // 'Bob', 'Eve' * console.log(values); // contains 7; * @example * // HashMap for user session caching O(1) performance * interface UserSession { * userId: number; * username: string; * loginTime: number; * lastActivity: number; * } * * // HashMap provides O(1) average-case performance for set/get/delete * // Perfect for session management with fast lookups * const sessionCache = new HashMap<string, UserSession>(); * * // Simulate user sessions * const sessions: [string, UserSession][] = [ * ['session_001', { userId: 1, username: 'alice', loginTime: 1000, lastActivity: 1050 }], * ['session_002', { userId: 2, username: 'bob', loginTime: 1100, lastActivity: 1150 }], * ['session_003', { userId: 3, username: 'charlie', loginTime: 1200, lastActivity: 1250 }] * ]; * * // Store sessions with O(1) insertion * for (const [token, session] of sessions) { * sessionCache.set(token, session); * } * * console.log(sessionCache.size); // 3; * * // Retrieve session with O(1) lookup * const userSession = sessionCache.get('session_001'); * console.log(userSession?.username); // 'alice'; * console.log(userSession?.userId); // 1; * * // Update session with O(1) operation * if (userSession) { * userSession.lastActivity = 2000; * sessionCache.set('session_001', userSession); * } * * // Check updated value * const updated = sessionCache.get('session_001'); * console.log(updated?.lastActivity); // 2000; * * // Cleanup: delete expired sessions * sessionCache.delete('session_002'); * console.log(sessionCache.has('session_002')); // false; * * // Verify remaining sessions * console.log(sessionCache.size); // 2; * * // Get all active sessions * const activeCount = [...sessionCache.values()].length; * console.log(activeCount); // 2; */ export declare class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> { /** * Create a HashMap and optionally bulk-insert entries. * @remarks Time O(N), Space O(N) * @param [entryOrRawElements] - Iterable of entries or raw elements to insert. * @param [options] - Options: hash function and optional record-to-entry converter. * @returns New HashMap instance. */ constructor(entryOrRawElements?: Iterable<R | [K, V]>, options?: HashMapOptions<K, V, R>); protected _store: { [key: string]: HashMapStoreItem<K, V>; }; /** * Get the internal store for non-object keys. * @remarks Time O(1), Space O(1) * @returns Internal record of string→{key,value}. */ get store(): { [p: string]: HashMapStoreItem<K, V>; }; protected _objMap: Map<object, V>; /** * Get the internal Map used for object/function keys. * @remarks Time O(1), Space O(1) * @returns Map of object→value. */ get objMap(): Map<object, V>; protected _toEntryFn?: (rawElement: R) => [K, V]; /** * Get the raw→entry converter function if present. * @remarks Time O(1), Space O(1) * @returns Converter function or undefined. */ get toEntryFn(): ((rawElement: R) => [K, V]) | undefined; protected _size: number; /** * Get the number of distinct keys stored. * @remarks Time O(1), Space O(1) * @returns Current size. */ get size(): number; protected _hashFn: (key: K) => string; /** * Get the current hash function for non-object keys. * @remarks Time O(1), Space O(1) * @returns Hash function. */ get hashFn(): (key: K) => string; /** * Check whether the map is empty. * @remarks Time O(1), Space O(1) * @returns True if size is 0. */ isEmpty(): boolean; /** * Remove all entries and reset counters. * @remarks Time O(N), Space O(1) * @returns void */ clear(): void; /** * Type guard: check if a raw value is a [key, value] entry. * @remarks Time O(1), Space O(1) * @returns True if the value is a 2-tuple. */ isEntry(rawElement: any): rawElement is [K, V]; /** * Insert or replace a single entry. * @remarks Time O(1), Space O(1) * @param key - Key. * @param value - Value. * @returns True when the operation succeeds. */ set(key: K, value: V): boolean; /** * Insert many entries from an iterable. * @remarks Time O(N), Space O(N) * @param entryOrRawElements - Iterable of entries or raw elements to insert. * @returns Array of per-entry results. */ setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[]; /** * Get the value for a key. * @remarks Time O(1), Space O(1) * @param key - Key to look up. * @returns Value or undefined. */ get(key: K): V | undefined; /** * Check if a key exists. * @remarks Time O(1), Space O(1) * @param key - Key to test. * @returns True if present. */ has(key: K): boolean; /** * Delete an entry by key. * @remarks Time O(1), Space O(1) * @param key - Key to delete. * @returns True if the key was found and removed. */ delete(key: K): boolean; /** * Replace the hash function and rehash the non-object store. * @remarks Time O(N), Space O(N) * @param fn - New hash function for non-object keys. * @returns This map instance. */ setHashFn(fn: (key: K) => string): this; /** * Deep clone this map, preserving hashing behavior. * @remarks Time O(N), Space O(N) * @returns A new map with the same content. */ clone(): this; /** * Map values to a new map with the same keys. * @remarks Time O(N), Space O(N) * @template VM * @param callbackfn - Mapping function (key, value, index, map) → newValue. * @param [thisArg] - Value for `this` inside the callback. * @returns A new map with transformed values. */ map<VM>(callbackfn: EntryCallback<K, V, VM>, thisArg?: any): any; /** * Filter entries into a new map. * @remarks Time O(N), Space O(N) * @param predicate - Predicate (key, value, index, map) → boolean. * @param [thisArg] - Value for `this` inside the predicate. * @returns A new map containing entries that satisfied the predicate. */ filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): any; /** * (Protected) Create a like-kind instance and seed it from an iterable. * @remarks Time O(N), Space O(N) * @template TK * @template TV * @template TR * @param [entries] - Iterable used to seed the new map. * @param [options] - Options forwarded to the constructor. * @returns A like-kind map instance. */ protected _createLike<TK = K, TV = V, TR = [TK, TV]>(entries?: Iterable<[TK, TV] | TR>, options?: any): any; protected _rehashNoObj(): void; protected _getIterator(): IterableIterator<[K, V]>; protected _isObjKey(key: any): key is object | ((...args: any[]) => any); protected _getNoObjKey(key: K): string; } /** * Hash-based map that preserves insertion order via a doubly-linked list. * @remarks Time O(1), Space O(1) * @template K * @template V * @template R * @example examples will be generated by unit test */ export declare class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> { protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>; /** * Create a LinkedHashMap and optionally bulk-insert entries. * @remarks Time O(N), Space O(N) * @param [entryOrRawElements] - Iterable of entries or raw elements to insert. * @param [options] - Options: hash functions and optional record-to-entry converter. * @returns New LinkedHashMap instance. */ constructor(entryOrRawElements?: Iterable<R | [K, V]>, options?: LinkedHashMapOptions<K, V, R>); protected _hashFn: (key: K) => string; get hashFn(): (key: K) => string; protected _objHashFn: (key: K) => object; /** * Get the hash function for object/weak keys. * @remarks Time O(1), Space O(1) * @returns Object-hash function. */ get objHashFn(): (key: K) => object; protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>>; /** * Get the internal record for non-object keys. * @remarks Time O(1), Space O(1) * @returns Record of hash→node. */ get noObjMap(): Record<string, HashMapLinkedNode<K, V | undefined>>; protected _objMap: WeakMap<object, HashMapLinkedNode<K, V | undefined>>; get objMap(): WeakMap<object, HashMapLinkedNode<K, V | undefined>>; protected _head: HashMapLinkedNode<K, V | undefined>; /** * Get the head node (first entry) sentinel link. * @remarks Time O(1), Space O(1) * @returns Head node or sentinel. */ get head(): HashMapLinkedNode<K, V | undefined>; protected _tail: HashMapLinkedNode<K, V | undefined>; /** * Get the tail node (last entry) sentinel link. * @remarks Time O(1), Space O(1) * @returns Tail node or sentinel. */ get tail(): HashMapLinkedNode<K, V | undefined>; protected _toEntryFn?: (rawElement: R) => [K, V]; get toEntryFn(): ((rawElement: R) => [K, V]) | undefined; protected _size: number; get size(): number; /** * Get the first [key, value] pair. * @remarks Time O(1), Space O(1) * @returns First entry or undefined when empty. */ get first(): [K, V] | undefined; /** * Get the last [key, value] pair. * @remarks Time O(1), Space O(1) * @returns Last entry or undefined when empty. */ get last(): [K, V] | undefined; /** * Iterate from head → tail. * @remarks Time O(N), Space O(1) * @returns Iterator of [key, value]. */ begin(): Generator<(K | V | undefined)[], void, unknown>; /** * Iterate from tail → head. * @remarks Time O(N), Space O(1) * @returns Iterator of [key, value]. */ reverseBegin(): Generator<(K | V | undefined)[], void, unknown>; /** * Insert or replace a single entry; preserves insertion order. * @remarks Time O(1), Space O(1) * @param key - Key. * @param [value] - Value. * @returns True when the operation succeeds. */ set(key: K, value?: V): boolean; setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[]; has(key: K): boolean; get(key: K): V | undefined; /** * Get the value at a given index in insertion order. * @remarks Time O(N), Space O(1) * @param index - Zero-based index. * @returns Value at the index. */ at(index: number): V | undefined; delete(key: K): boolean; /** * Delete the first entry that matches a predicate. * @remarks Time O(N), Space O(1) * @param predicate - Function (key, value, index, map) → boolean to decide deletion. * @returns True if an entry was removed. */ deleteWhere(predicate: (key: K, value: V | undefined, index: number, map: this) => boolean): boolean; /** * Delete the entry at a given index. * @remarks Time O(N), Space O(1) * @param index - Zero-based index. * @returns True if removed. */ deleteAt(index: number): boolean; isEmpty(): boolean; isEntry(rawElement: any): rawElement is [K, V]; clear(): void; clone(): any; filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): any; /** * Map each entry to a new [key, value] pair and preserve order. * @remarks Time O(N), Space O(N) * @template MK * @template MV * @param callback - Mapping function (key, value, index, map) → [newKey, newValue]. * @param [thisArg] - Value for `this` inside the callback. * @returns A new map of the same class with transformed entries. */ map<MK, MV>(callback: EntryCallback<K, V, [MK, MV]>, thisArg?: any): any; protected _getIterator(): IterableIterator<[K, V]>; protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): boolean; protected _createLike<TK = K, TV = V, TR = [TK, TV]>(entries?: Iterable<[TK, TV] | TR>, options?: any): any; }