什么是JavaScript等同于C#HashSet?


79

我有几千个整数键的列表。我唯一需要处理的就是说列表中是否有给定的值。

对于C#,我将使用HashSet来快速进行查找。什么是JavaScript等效项?


最低支持级别:IE 9 +,jQuery(当前)


10
通常是一个对象。
pswg 2014年


我同意这是重复的(尽管不是每个人都喜欢使用地图作为集合。),但是链接问题中的答案缺少下面发现的许多特质和注释。
user2864740 2014年

6
不是重复的-HashSet和Dictionary非常不同。字典让您检索对象。HashSet不允许您检索对象,而只能告诉您对象是否存在。
Kees C. Bakker 2014年

3
从字面上看,这些答案都没有一个错过HashSet <T>的要点之一吗?它仅允许唯一项。
user9993

Answers:


81

在后台,JavaScript对象是通过哈希表实现的。所以,你的那Key:Value(your integer):true

恒定时间查找功能可以实现为:

var hash = {
  1:true,
  2:true,
  7:true
  //etc...
};

var checkValue = function(value){
  return hash[value] === true;
};


checkValue(7); // => true
checkValue(3); // => false

4
真好 但是,还需要注意一件事,如果您想进行(哈希中的num 迭代,则此处的num(存储为键)是字符串类型。
Rongsir '16

(散列中的值)只需将属性注册为空值就足够了-甚至不是真正的布尔值,并使用delete hash [value]删除即可
Demetris Leptos

3
javascript中有一个Set对象,可以更好地满足此人的需求。
remydib '18年

4
ECMAScript的符合规范的Set.has()函数明确地定义为直到找到一个匹配通过整个集合的迭代。这似乎不符合OP规定的其他语言中的HashSet之类的快速查找目标。
JD Sandifer

4
@JDSandifer:同一规范还指出:“ Set对象必须使用哈希表或其他机制实现,这些机制平均提供的访问时间对集合中元素的数量而言是次线性的。Set对象中使用的数据结构规范仅旨在描述Set对象所需的可观察的语义,而并非旨在成为可行的实现模型。” 在现代JavaScript中,当您需要集合或地图时Set,这Map是最好的选择。
jmrk

103

实际上,JavaScript提供了一个Set对象,使用起来相当简单:

var set = new Set();
set.add(1);
set.add(2);

set.has(1)    // true

不幸的是,它与IE9不兼容。


15
这应该是2018
。– Anders Tornblad

1
@LexJacobs:阅读该规范中有关Set对象的介绍。需要实现比O(n)更快的查找,实际上这意味着O(log n)或O(1)。
jmrk

在哪里可以找到它的实现,它是HashSet还是AVL树?
旅行者

35

使用一个对象。要将密钥添加到集合中,请执行以下操作:

object[key] = true;

要测试密钥是否在集合中,请执行以下操作:

if (object.hasOwnProperty(key)) { ... }

要从集合中删除密钥,请执行以下操作:

delete object[key]

2
unset?运算符delete在JS中!
gsnedders 2014年

谢谢,正要验证语法
Barmar 2014年

3
测试密钥是否在集合中的正确方法是使用object.hasOwnProperty(key)。否则,"toString" in object == true
巴特2014年

5
hasOwnProperty运行缓慢,如果有一个名为hasOwnProperty的键怎么办?使用o = Object.create(null); 创建“哈希集”而不是文字,然后可以使用快速属性访问来检查键成员身份,而不是方法的hasOwnProperty(),而不必担心这样做时会发生属性冲突。
dandavis 2014年

8

您可以仅使用常规JavaScript对象和'in'关键字来查看该对象是否具有特定键。

var myObj = {
  name: true,
  age: true
}

'name' in myObj //returns true;
'height' in myObj // returns false;

或者,如果您知道您将在对象中使用可能在JavaScript对象属性中构建的键,则使用...

var myObj = {
  name: true,
  age: true
}

myObj.hasOwnProperty('name') //returns true;
myObj.hasOwnProperty('height') // returns false;

myObj中的'toString'//返回true
Barmar

2
如果有一个名为“ hasOwnProperty”的密钥怎么办?
dandavis

24
然后,您重新评估自己的生活。
泰勒·麦金尼斯

@TylerMcGinnis大声笑-我认为它仍然可以工作-但是,是的,请重新评估为什么拥有一个名为hasOwnProperty ..的属性,并且无论如何都使用“ in”
Demetris Leptos

1
我们似乎已经忘记了没有涵盖将对象作为键的情况..除非您用'$ id'(我是newtonsoft启发的)或'__ id __'递增地标识所有对象,然后用作对象时将其用作键。。hash [isNotPrimitive(key)?key ['$ id']:key]
Demetris Leptos

1

我已经阅读了解决方案,并尝试了一些。尝试使用该object[key]方法后,我意识到它行不通。我想要一个可以存储HTML元素的HashSet。当添加这些对象时,它key被翻译成字符串,因此我想出了自己的基于jQuery的集合。它支持addremovecontainsclear

var HashSet = function () {

    var set = [];

    this.add = function (obj) {
        if (!this.contains(obj)) {
            set.push(obj);
        }
    };

    this.remove = function (obj) {
        set = jQuery.grep(set, function (value) {
            return value !== obj;
        });
    };

    this.clear = function () {
        set = [];
    };

    this.contains = function (obj) {
        return $.inArray(obj, set) > -1;
    };

    this.isEmpty = function () {
        return set.length === 0;
    };
};

注意
$('#myElement')集合中添加类似内容时,应添加真实的HTML元素$('#myElement')[0]。哦...而且,如果您想保留已更改控件的列表,请使用元素的名称(给我一个:radio控件问题)。

注意2
我认为object[key]整数可能会更快。

注意3
如果仅存储数字或字符串,则此设置将更快:

var HashSet = function () {

    var set = {};

    this.add = function (key) {
        set[key] = true;
    };

    this.remove = function (key) {
        delete set[key];
    };

    this.clear = function () {
        set = {};
    };

    this.contains = function (key) {
        return set.hasOwnProperty(key);
    };

    this.isEmpty = function () {
        return jQuery.isEmptyObject(set);
    };
};

3
这根本不是一个HashSet ...它不符合人们期望HashSet满足的任何标准
Andrew Whitaker 2014年

它没有HashSet的O1性能,这是事实。但是它模仿了C#的HashSet函数。
Kees C. Bakker 2014年

3
不,它模仿了HashSet实现的ICollection接口msdn.microsoft.com/zh-cn/library/92t2ye13%28v=vs.110%29.aspx。HashSet的关键点通常是O(1)查找时间,而您提供的第一个实现的行为与List更相似,即O(N)。
Oskar Berggren 2014年

1
@OskarBerggren-Note3提供的集合应该没有问题,应该为O1。
Kees C. Bakker 2014年

1

地图,或者如果不需要迭代WeakMap

let m1=new Map();

m1.set('isClosed',false);
m1.set('isInitialized',false);

m1.set('isClosed',true);

m1.forEach(function(v,k)
{
    console.log(`${k}=${v}`);
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.