如何在Javascript中获得真实的地图和集合

How to get real maps and sets in Javascript?

本文关键字:真实 地图 集合 Javascript      更新时间:2024-04-20

Javascript是一种简洁的语言,但似乎缺乏一些非常基本的功能,如映射和集合。

Map是一个键/值存储区,其中键和值可以是任意对象,每个键最多有一个值,通过严格的相等来区分。

Set与映射相同,只是它没有值,并且您只对存在感兴趣,同样是严格相等。

如果我想使用这些ADT,我们在javascript中最接近的是Object,它几乎是正确的,但将所有键强制为字符串,这使得它对一些实际集和映射将用于的事情毫无用处。

给定映射,集合是平凡的:set[key] = true而不是set[key] = value。或者可以用Arrays、Array.indexOf和Array.splice实现全集功能(对于小集)。添加并行值列表将提供映射功能。对于较大的数据集,可以在普通对象之上实现哈希表,但我认为这将成为一个更严肃的项目。

因此,我的问题是,是否有比上述建议更惯用的实现(或更简单的解决方案)来从Javascript中获得完整的Map/Set功能?还是每个人都对此忍气吞声?

编辑所以看起来es6地图/集规范是可行的。我会接受一个链接到/显示简单可用垫片的答案。

不幸的是,在Javascript中无法做到这一点。

然而

似乎没有比在OP中咬紧牙关地提出建议更惯用的解决方案了。然而,正如其他贡献者所指出的,映射和集合正在ES6中出现,并且有一个可执行规范。

ES6可执行规范使用了OP中建议的映射实现,并在此基础上实现了集合;映射是作为一个键阵列和一个vals阵列完成的,与array.splice和线性扫描保持平行。不幸的是,它似乎使用了一些在主流JS中不可接受的深奥语法。

为了给我们提供一个可用的填充程序,我获取了链接的规范,经过一些修改将其转换为coffeescript,并编写了一些测试来演示功能。代码在我的github:上

#A non-stupid alternative to Array.prototype.indexOf
indexOfIdentical = (keys, key) ->
    for i of keys
        if keys[i] == key
            return i
    return -1
class Map
    constructor: (a = []) ->
        @keys = [];
        @vals = [];
        for [k,v] in a
            @set k, v
    get: (key) ->
        i = indexOfIdentical @keys, key
        return if i < 0 then undefined else @vals[i]
    has: (key) ->
        return 0 <= indexOfIdentical @keys, key
    set: (key, val) ->
        i = indexOfIdentical @keys, key
        if i < 0
            i = @keys.length
        @keys[i] = key
        @vals[i] = val
    del: (key) ->
        i = indexOfIdentical @keys, key
        if i < 0
            return false
        @keys.splice i, 1
        @vals.splice i, 1
        return true
class Set
    constructor: (a = []) ->
        @keys = []
        for key in a
            @add key
    has: (key) ->
        return 0 <= indexOfIdentical @keys, key
    add: (key) ->
        i = indexOfIdentical @keys, key
        if i < 0
            i = @keys.length
        @keys[i] = key
    del: (key) ->
        i = indexOfIdentical @keys, key
        if i < 0
            return false
        @keys.splice i, 1
        return true
#this is implemented as a simple node.js module:
#include with mapset = require("./path/to/mapset.js")
module.exports = {Map: Map, Set: Set}

不,没有但是Javascript对象是最接近集合和映射的表示。

以下是它们的不同使用方式:

var foo = {]
// The following two are the same thing.
foo.bar = true; 
foo['bar'] = true; 
var bar = 'bar';
foo[bar] = true; // again, the same thing.

var foo = { bar: true }

它们可以很容易地迭代:

for (item in foo) {
  if (foo.hasOwnProperty[item]) {
    console.log(item); // --> returns 'bar';
    console.log(foo[item]); // --> returns true;
  }
}

检查属性的存在:

if (foo[bar] !== undefined) {
  // ... it doesn't
}
// If one declares a property without any value,
foo.bar;
//It will still come out as undefined
console.log(foo.bar); // --> undefined