JavaScript中是否有一个索引值的集合?

时间:2019-03-01 02:02:21

标签: javascript dictionary data-structures

我的问题很简单:JavaScript中是否存在可以按对象的值编制索引,可以按对象的值进行检索并可以根据需要将键作为对象提供的集合?

我的用例是需要一个可以按坐标索引的容器,例如x,y,z (是的,我知道我可以创建3D数组)。

我不仅仅知道标准对象通过字符串索引和检索,为对象设置toString()函数可以透明地设置和检索(某种程度上)。

我还知道Map<key, value>使用任意类型作为键,但是随后使用标准===比较键,这意味着值相等的两个对象不会映射到相同的值。

本质上,我想要的是一个实际上使用键值而不是对象标识来检索和提供值的Map。在我看来,这似乎是一个非常常见的用例,但我似乎找不到任何满足它的npm库。我真的不想自己动手做,所以有没有图书馆或可以用来实现目标的东西?我认为我的搜索字词严重超载。

一些简单的代码来演示:

class Coord {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() { return `${this.x}, ${this.y}`; }
}

let valueMap = new Map();
valueMap.set(new Coord(1, 1), `A set value`);
console.log(valueMap.get(new Coord(1, 1))); // prints 'undefined', 
                                            // want to get: 'A set value'

2 个答案:

答案 0 :(得分:2)

Immutable.js提供了这一点,但是它要求您仅使用不可变的类型和基元。这将意味着使用Immutable的Record类型而不是类 * 。在这种情况下,您的示例如下所示:

const { Record, Map } = require('immutable');
const Coord = Record({ a: 0, b: 0 }); // Record fields have default values

const valueMap = new Map().set(Coord(1, 1), `A set value`);
console.log(valueMap.get(Coord(1, 1))); // Logs "A set value"

Immutable.js可能不是您想要的,因为它的集合都是不可变的。每个操作都返回一个新集合,而不是修改原始集合。幸运的是,由于结构共享的魔力,这比人们预期的要快得多。

我已经看到了许多替代方案,但是它们要么实施不正确(例如,按照您的toString示例的方式假设哈希的唯一性),要么在构建地图时遇到了严重的复杂性或性能问题。例如,Immutable.js允许您将地图(或集合,列表或集合地图等)用作另一个地图中的键。我见过的少数几个库正确地将散列和相等函数用作映射的参数,或者将这种复杂性泄漏给最终用户,或者在这种情况下具有更差的性能。最后,如果存储的对象发生突变,则依赖哈希值的库可能会出现问题,因此使用强制不变性的库可以帮助避免踩枪。

如果您不喜欢Immutable.js,则可以使用一些类似的库。 Mori是JS中原始的结构不可变共享库,它提供了一些具有值语义的数据结构(包括地图),但基于Clojure,并且具有非常非惯用的JavaScript接口。这两个库都使用哈希数组映射尝试提供不可变结构的有效实现,并且此类型在hamt.js中可用。但是,hamt非常简单,与前两个相比,它提供了更具挑战性和可组合性的界面。


* 从技术上讲,您可以通过实现Value Object interface并将equalshashCode方法放在类上来使用自己的类,但是我相信您可以如果您的对象在Immutable.js集合中发生了突变,就会遇到问题,因此使用Records可能更安全。

答案 1 :(得分:-1)

如果两个对象指向相同的引用,则两个对象相等。从对象引用获取字符串值也没有意义。您可以在对象中设置此字符串。