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

如何在Javascript中获得真实的贴图和集合?,javascript,data-structures,Javascript,Data Structures,Javascript是一种简洁的语言,但似乎缺少一些非常基本的功能,如映射和集合 映射是一种键/值存储,其中键和值可以是任意对象,每个键最多有一个值,通过严格相等来区分 集合与映射相同,不同的是它没有值,而且你只对存在感兴趣,同样是严格相等 如果我想使用这些ADT,我们在javascript中最接近的是对象,这几乎是正确的,但强制所有键为字符串,这使得它对于某些真正的集合和映射将无法使用 给定映射,集合很简单:set[key]=true而不是set[key]=value。或者可以使用Array、

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

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

集合与映射相同,不同的是它没有值,而且你只对存在感兴趣,同样是严格相等

如果我想使用这些ADT,我们在javascript中最接近的是对象,这几乎是正确的,但强制所有键为字符串,这使得它对于某些真正的集合和映射将无法使用

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

因此,我的问题是,有没有比上述建议更惯用的实现(或更简单的解决方案)来实现Javascript的完整映射/设置功能?还是每个人都在这件事上咬紧牙关

编辑,这样看来这才是正确的选择。我会接受一个链接到/显示一个简单可用的垫片的答案。

不,没有。但是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.

它们可以很容易地进行迭代:

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

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


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

ES6可执行规范使用OP中建议的映射实现,并根据该映射实现集合;映射作为键阵列和VAL阵列进行,并与array.splice和线性扫描并行维护。不幸的是,它似乎使用了一些在主流JS中不可接受的深奥语法

为了给我们提供一个可用的垫片,我对链接的规范进行了修改,将其转换为coffeescript,并编写了一些测试来演示其功能。代码是:

#Array.prototype.indexOf的非愚蠢替代品
indexOfIdentical=(键,键)->
因为我有很多钥匙
如果键[i]==键
返回i
返回-1
类图
构造函数:(a=[])->
@键=[];
@VAL=[];
对于a中的[k,v]
@设定k,v
获取:(键)->
i=键、键的索引可信度
如果i<0则返回未定义的else@vals[i]
has:(键)->
返回0
i=键、键的索引可信度
如果i<0
i=@keys.length
@键[i]=键
@val[i]=val
德尔:(钥匙)->
i=键、键的索引可信度
如果i<0
返回错误
@键1.1
@VAL.i,1
返回真值
类集
构造函数:(a=[])->
@键=[]
钥匙
@添加键
has:(键)->
返回0
i=键、键的索引可信度
如果i<0
i=@keys.length
@键[i]=键
德尔:(钥匙)->
i=键、键的索引可信度
如果i<0
返回错误
@键1.1
返回真值
#这是一个简单的node.js模块:
#include with mapset=require(“./path/to/mapset.js”)
module.exports={Map:Map,Set:Set}

FYI,这两种数据结构将用于JavaScript,一个实验性的实现是。您可能想看看。考虑到映射和集合在ES6中都有自己的API,即使您(可能)无法获得与本机实现相同的性能,它们也是可屏蔽的。我用Javascript实现了Java版本。它很好用。@IngoBürk:错;无法获取任意对象的引用哈希代码。(除非你变异它)@SLaks有:0。这是一个愚蠢的散列,但根据散列代码契约,这是完全合法的,这正是他在问题中所说的。请仔细阅读。问题会明确说明和拒绝对象。正如在对我(现已删除)答案的评论中指出的,它们不合适,因为它们的属性名称都是强制使用字符串的。。。。钥匙不能是任意的。
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