kitta
kitta

Reputation: 2069

Typescript, HashMap using hashcode and equal function

I'm writing a typescript browser game.

I need to store an int vector3 (map position) as the map key.

Since we can't store reference type into the key of typescript Object and Map. (I mean we could for Map but cannot lookup without holding the same reference)

And there are solutions are suggested on the internet such as nested maps or stringify keys.

I want to find a more elegant solution using hashcode and equals.

Is there any suggest solution or npm library?

Upvotes: 0

Views: 1018

Answers (1)

aroyer
aroyer

Reputation: 111

In as much as I could not answer the question easily for myself from what I had found on the Internet, I share a quick implementation, borrowed from Python experience (not fully tested).

The idea is to have the Hashable.hash() function return a number or a string that will let the HashableMap know when key objects are actually the same.

export interface Hashable {
    hash(): InnerHashKey;
}

export class HashableMap<K extends Hashable, V> extends Map<K, V> {
    private readonly _innerMap: InnerMap<K, V> = new InnerMap<K, V>();

    // Map<K, V> interface overload.
    public get(key: K): V | undefined {
        return this._innerMap.get(key.hash())?.value;
    }
    public has(key: K): boolean {
        return this._innerMap.has(key.hash());
    }
    public set(key: K, value: V): this {
        this._innerMap.set(key.hash(), {key: key, value: value});
        return this;
    }
    public delete(key: K): boolean {
        return this._innerMap.delete(key.hash());
    }
    public get size(): number {
        return this._innerMap.size;
    }
    public forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
        this._innerMap.forEach((value: InnerValue<K, V>): void => callbackfn(value.value, value.key, thisArg));
    }
    public entries(): IterableIterator<[K, V]> {
        return Array.from(this._innerMap.values()).map((value: InnerValue<K, V>): [K, V] => [value.key, value.value]).values();
    }
    public keys(): IterableIterator<K> {
        return Array.from(this._innerMap.values()).map((value: InnerValue<K, V>): K => value.key).values();
    }
    public values(): IterableIterator<V> {
        return Array.from(this._innerMap.values()).map((value: InnerValue<K, V>): V => value.value).values();
    }
    public clear(): void {
        this._innerMap.clear();
    }
}

type InnerHashKey = any;
type InnerValue<K, V> = {key: K, value: V};
class InnerMap<K, V> extends Map<InnerHashKey, InnerValue<K, V>> {}

Upvotes: 1

Related Questions