【问题标题】:Typescript, HashMap using hashcode and equal functionTypescript, HashMap 使用哈希码和相等函数
【发布时间】:2021-11-20 13:51:52
【问题描述】:

我正在写一个打字稿浏览器游戏。

我需要存储一个 int vector3(地图位置)作为地图键。

由于我们不能将引用类型存储到 typescript Object 和 Map 的键中。 (我的意思是我们可以使用 Map 但如果没有相同的引用就无法查找)

而且网上也有一些解决方案,比如嵌套映射或者字符串化键。

我想找到一个更优雅的使用 hashcode 和 equals 的解决方案。

是否有任何建议的解决方案或 npm 库?

【问题讨论】:

  • 为什么 hashcode/equals 比字符串化键更“优雅”?前者意味着您必须实现一个多重映射,以存储具有相同哈希码的所有键。如果您可以计算唯一键,那么您可以使用常规映射。对于三个整数的向量,您只需执行 join 即可获得这样的密钥。
  • 我不想进行字符串化,因为这需要在每一帧中操作许多字符串。我正在寻找的可能方法是按照您所说的计算哈希。但问题是由于 int vector3 使用 3 个整数,因此肯定有可能发生冲突以将其散列为 1 个整数。除了我要限制vector3中每个int的范围。
  • @jcalz BTW,感谢您的建议。计算唯一哈希也在我的考虑范围内。
  • 您是否有证据表明将数字连接成字符串比使用多映射解决哈希冲突要慢?假设简单的解决方案将具有不可接受的性能似乎是为时过早的优化。
  • 我也对这个问题感兴趣,不是因为性能问题,而是类型检查:我觉得字符串化键破坏了使用打字稿的兴趣。网上也没找到太多:npm hashmap 离它不远,剩下的待办事项:“允许以 AOP 方式或通过传递服务来扩展散列函数”:(

标签: typescript hashmap


【解决方案1】:

尽管我无法根据我在 Internet 上找到的内容轻松回答这个问题,但我分享了一个快速实现,借鉴了 Python 经验(未经过全面测试)。

这个想法是让Hashable.hash() 函数返回一个number 或一个string,这将使HashableMap 知道关键对象何时实际上是相同的。

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>> {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多