【问题标题】:Is there a data structure like the Java Set in JavaScript? [duplicate]JavaScript 中是否有类似 Java Set 的数据结构? [复制]
【发布时间】:2011-05-19 15:05:12
【问题描述】:

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

我想实现以下相同的行为(此代码是 Java 代码):

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

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

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

【问题讨论】:

    标签: java javascript dojo set


    【解决方案1】:

    我已经编写了一个 JavaScript HashSet 实现,它可以满足您的需求并允许任何对象成为集合的成员:http://code.google.com/p/jshashtable

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

    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;
        };
    }
    

    关于实现的注释:valStringSet 实现内部使用的对象,每个集合都是唯一的。将属性名称构成集合 (setObj) 的对象的属性值与 val 进行比较,无需进行 hasOwnProperty() 检查,并保证只有已添加到集合中的字符串才会显示在 values .

    示例用法:

    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"]
    

    【讨论】:

    • 避免调用hasOwnProperty()的目的是什么?相等性检查更快吗?如果有,你怎么知道?
    • @JørgenFogh:我怀疑相等性检查可能会更快,因为它避免了函数调用的开销。不过我还没有测试过,所以请随意创建一个基准;我很想看看结果。
    • @JørgenFogh:对象比较的另一个优点是它不可能出错。
    【解决方案2】:

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

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

    这是一个更高级的用例:

    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 //
    

    删除项目可以这样完成:

    delete x['key'];
    

    【讨论】:

    • 感谢回复:我想先动态添加许多键到对象,然后我想检查对象中是否存在键。我该怎么做?
    • @键可以是任何字符串(甚至是包含字符串的变量)。我会更新一个例子。
    • @GB 与delete x['key'];。再次,关键可以是任何东西。为了方便,我使用了文字。
    • 不一定:Object.prototype.foo = "true"; alert(x["foo"] == true)
    • 如果您正在创建一个简单的对象并且原型不是问题,只需使用“in”运算符。它读起来好多了。像 x["foo"] 这样的静态查找可以写成 x.foo。
    【解决方案3】:

    不需要 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
    }
    

    【讨论】:

    • forEach 在 IE 中不受支持。这也需要hasOwnProperty() 检查以防其他代码完成了类似Object.prototype.aks = 1 的操作。
    • 是的,在我的示例中,我假设 ES5 并且没有人修改 Object 原型,这是最佳实践。
    【解决方案4】:

    可能使用关联数组/哈希表/字典(我不知道它的确切名称),使用集合元素作为键,使用“任何其他”作为值。

    insert: mySet[key] = "Whatever";
    
    delete: mySet[key] = null;
    
    check: if (mySet[key] != null) { ... }
    

    【讨论】:

    • 感谢回复。但是如何检查它是否包含密钥?
    • 我想用javascript实现它
    • 查看上次编辑,试图澄清。
    • @GB 它被称为对象。它是 JavaScript 的基本数据类型。
    • @GB 实际上,在您的check 情况下,正确的做法是与undefined 进行比较:if (mySet[key] !== undefined) { ... }。在 JavaScript 中,项目仍然可以存在并具有值 null 更正:正确检查的唯一方法是使用 hasOwnProperty
    【解决方案5】:

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

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

    例如:

    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
    

    【讨论】:

      【解决方案6】:

      集合没有键。它们只有一组值,但映射有成对的键/值实体。

      因此,您有 2 个选择。它们各有优缺点:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-20
        • 2010-09-05
        • 2015-05-20
        • 1970-01-01
        • 2017-05-29
        • 2015-04-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多