有没有像 JavaScript 中的 Java Set 这样的数据结构?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4343746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 16:13:14  来源:igfitidea点击:

Is there a data structure like the Java Set in JavaScript?

javajavascriptdojoset

提问by aks

I want to use a data structure in JavaScript that can be used to store number of IDs. I should be able to check if a key already exists in that set, something like Java Sets.

我想在 JavaScript 中使用可用于存储 ID 数量的数据结构。我应该能够检查该集合中是否已经存在一个键,例如 Java Sets。

I want to achive same behaviours as follows (this code is in Java):

我想实现如下相同的行为(此代码使用 Java):

Set<String> st = new HashSet<String>();
//add elemets

if(st.contains("aks") ){
  //do something
}

I want a JavaScript/dojo equivalent of the above code.

我想要一个与上述代码等效的 JavaScript/dojo。

回答by G B

Possibly with an associative array / Hashtable / dictionary (I don't know how it's called exactly), using the set elements as keys and "anything else" as values.

可能使用关联数组/哈希表/字典(我不知道它是如何准确调用的),使用集合元素作为键和“其他任何东西”作为值。

insert: mySet[key] = "Whatever";

delete: mySet[key] = null;

check: if (mySet[key] != null) { ... }

回答by Alin Purcaru

Why not use a normal object and check if a key exists with JavaScript's hasOwnProperty?

为什么不使用普通对象并检查 JavaScript 的键是否存在hasOwnProperty

var x = {};
x['key'] = 'val';
x.hasOwnProperty('key'); // true //
x.hasOwnProperty('key2'); // false //

And here is a more advanced use case:

这是一个更高级的用例:

var x = {};
var prefix = 'item_';
for(var i=0;i<10;i++){
   x[prefix+i] = 'value '+(i+1);
}
x.hasOwnProperty('item_6'); // true //
x.hasOwnProperty('other key'); // false //

Removing items can be done like this:

删除项目可以这样完成:

delete x['key'];

回答by fifigyuri

Hash is good candidate for implementing Set. You could create a set using a function like that:

Hash 是实现 Set 的理想选择。您可以使用这样的函数创建一个集合:

function set () {
    var result = {};
    for (var i = 0; i < arguments.length; i++) result[arguments[i]] = true;
    return result;
}

For instance:

例如:

x = set([1,2,2,4])
x[1] #==> true
x[3] #==> false
x[5] = true; # add element to the set
x[5] = false; # remove element from the set

回答by Alexandr

Sets don't have keys. They only have set of values, but maps have pairs of key/value entities.

套装没有钥匙。它们只有一组值,但映射有成对的键/值实体。

As a result, you have 2 options. Each of them has its drawbacks and advantages:

因此,您有 2 个选择。它们中的每一个都有其缺点和优点:

  1. You can use as described above JavaScript object. Actually it is a map/associative array/hash table. One of its advantage - you can guarantee with this kind of structure that keys - are unique items. Its drawback connected to the issue - you have to keep some extra information that you don't need at all. Values of maps. trues or some other values. It does not matter. Why do you need them?

  2. To resolve the previous disadvantage you may consider using JavaScript arrays. But, you'll have to write some wrappers so arrays's behavior will look like sets behavior. Also operations that will search by the uniqueId will be slower than the same ones for hashtables cause you'll have to iterate via all items of an array.

  1. 您可以使用如上所述的 JavaScript 对象。实际上它是一个映射/关联数组/哈希表。它的优势之一 - 您可以使用这种结构保证键 - 是唯一的项目。它的缺点与这个问题有关——你必须保留一些你根本不需要的额外信息。地图的价值。真值或其他一些值。没关系。你为什么需要它们?

  2. 为了解决之前的缺点,您可以考虑使用 JavaScript 数组。但是,您必须编写一些包装器,以便数组的行为看起来像集合行为。此外,通过 uniqueId 搜索的操作将比哈希表的相同操作慢,因为您必须遍历数组的所有项目。

So, I think you should prefer hashtables to arrays, examples you can find in other posts. But probably you should consider changing of your data structure. don't keep uniqueId as keys with unselerss values if its possible. Let your unique ids point to some real objects for which these unique ids are used.

所以,我认为你应该更喜欢哈希表而不是数组,你可以在其他帖子中找到例子。但也许你应该考虑改变你的数据结构。如果可能,不要将 uniqueId 作为具有 unselers 值的键。让您的唯一 ID 指向一些使用这些唯一 ID 的真实对象。

PS: one more thing. Arrays are also objects actually. As a result they can be used as hashtables/maps too.

PS:还有一件事。数组实际上也是对象。因此,它们也可以用作哈希表/映射。

回答by Tim Down

I've written a JavaScript HashSet implementation that does what you want and allows any object to be a member of the set: http://code.google.com/p/jshashtable

我已经编写了一个 JavaScript HashSet 实现,它可以执行您想要的操作并允许任何对象成为该集合的成员:http: //code.google.com/p/jshashtable

However, if you just need to store strings, you could do something more simply by storing set members as property names of a normal Object. For example:

但是,如果您只需要存储字符串,您可以通过将集合成员存储为普通对象的属性名称来做更简单的事情。例如:

function StringSet() {
    var setObj = {}, val = {};

    this.add = function(str) {
        setObj[str] = val;
    };

    this.contains = function(str) {
        return setObj[str] === val;
    };

    this.remove = function(str) {
        delete setObj[str];
    };

    this.values = function() {
        var values = [];
        for (var i in setObj) {
            if (setObj[i] === val) {
                values.push(i);
            }
        }
        return values;
    };
}

A note about the implementation: valis an object used internally by the StringSetimplementation that is unique to each set. Comparing property values of the object whose property names make up the set (setObj) against valeliminates the need for a hasOwnProperty()check and guarantees that only strings that have been added to the set will show up in values.

关于实现的注意事项:val是实现内部使用的对象StringSet,对于每个集合都是唯一的。将属性名称构成 set( setObj)的对象的属性值与其进行比较val消除了hasOwnProperty()检查的需要,并保证只有已添加到集合中的字符串才会出现在values.

Example usage:

用法示例:

var set = new StringSet();
set.add("foo");
set.add("bar");

alert(set.contains("foo")); // true
alert(set.contains("baz")); // false

set.values(); // ["foo", "bar"], though not necessarily in that order
set.remove("foo");
set.values(); // ["bar"]

回答by peller

No Dojo needed, this is native to Javascript. Use Objects. Sounds like you only need the keys, not the values. Lookup is constant time.

不需要 Dojo,这是 Javascript 原生的。使用对象。听起来你只需要键,而不是值。查找是恒定时间。

var st = {'aks':1, 'foo':1, 'bar':1};  // or could start with empty {}. 1 could be any value of any type, it's just short.

//add elements
st.baz = 1;

//or load up dynamically

myArrayOfStrings.forEach(function(key){
 st[key] = 1;
});


if("aks" in st){
  //do something
}