ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JS中Set的基本使用和介绍

2022-06-25 16:01:23  阅读:139  来源: 互联网

标签:Set const 介绍 alert add 集合 new JS


一、基本介绍

  ES6新增的Set是一种新集合类型,为这门语言带来了集合数据结构。Set在很多方面都像是加强的Map,这是因为它们的大多数API和行为都是共有的。

 

二、基本API

使用new关键字和Set构造函数可以创建一个空集合:

const m=new Set();

如果想在创建的同时初始化实例,则可以给Set构造函数传入一个可迭代对象,其中需要包含插入到新集合实例中的元素:

//使用数组初始化集合
const m=new Set(["val1","val2","val3"]);

alert(s1.size);       //3

//使用自定义迭代器初始化集合
const s2=new Set({
   [Symbol.iterator]:function*(){
      yield "val1";
      yield "val2";
      yield "val3";  
}
});

alert(s2.size);       //3

初始哈之后,可以使用add()增加值,使用has()查询,通过size取得元素数量,以及使用delete()和clear()删除元素。

const s=new Set();

alert(s.has("Matt"));   //false

alert(s.size);     //0



a.add("Matt").add("Frisble");

alert(s.has("Matt"));      //true

alert(s.size):    //2

s.delete("Matt");
alert(s.has("Matt")); //false
alert(s.has("Frisble")); //true
alert(s.size); //1

s.clear(); //销毁集合实例中的所有值。

alert(s.has("Matt")); //false
alert(s.has("Frisble")); //false
alert(s.size);         //0

add()返回集合的实例,所以可以将多个添加操作连缀起来,包括初始化:

const s=new Set().add("val");

s.add("val2").add("val3");

alert(s.size);    //3

与Map类似,Set包含任何JavaScript数据类型作为值。集合也使用SameValueZero操作(ECMAScript 内部定义,无法在语言中使用),基本上相当于使用严格对象相等标准来检查值的匹配性。

const s=new Set();

const functionVal=function() {}
const symbolVal=Symbol();
const objectVal=new Object();

s.add(functionVal);
s.add(symbolVal);
s.add(objectVal);

alert(s.has(functionVal));       //true
alert(s.has(symbolVal));       //true
alert(s.has(functionVal));       //true

//SameValueZero检查意味着独立的实例不会冲突
alert(s.has(function(){}));  //false

与严格相等一样,用作值的对象和其他“集合”类型在自己的内容或属性被修改时也不会改变:

const s=new Set();

const objVal={},
        arrVal=[];

s.add(objVal);
s.add(arrVal);

objVal.bar="bar";
arrVal.push("bar");

alert(s.has(objVal));   //true
alert(s.has(arrVal));   //true

add()和delete()操作是幂等的。delete()返回一个布尔值,表示集合中是否存在要删除的值:

const s=new Set();

s.add("foo");
alert(s.size);    //1
s.add("foo");
alert("s.size");  //1

//集合里有这个值
alert(s.delete("foo"));   //true

//集合里没有这个值
alert(s.delete("foo"));    //false

三、顺序与迭代

  Set会维护值插入时的顺序,因此支持按顺序迭代。

  集合实例可以提供一个迭代器(Iterator),能以插入顺序生成集合内容。可以通过values()方法及其别名方法keys()(或者Symbol.iterator属性,它引用values())取得这个迭代器。

const s=new Set(["val1","val2","val3"]);

alert(s.values===s[Symbol.iterator]);   //true
alert(s.keys===s[Symbol.iterator]);     //true

for(let value of s.values()){
  alert(value);  
}

//val1
//val2
//val3

for (let value of s[Symbol.iterator]()){
  alert(value);  
}

//val1
//val2
//val3

因为values()是默认迭代器,所以可以直接对集合实例使用扩展操作,把集合转换为数组:

const a=new Set(["val1","val2","val3"]);

for(let pair of s.entries()){
  console.log(pair);  
}

//["val1","val1"]
//["val2","val2"]
//["val3","val3"]

集合的entries()方法返回一个迭代器,可以按照插入顺序产生包含两个元素的数组,这两个元素是集合中每个值的重复出现:

const s=new Set(["val1","val2","val3"]);

for(let pair of s.entries()){
  console.log(pair) ; 
}

//["val1","val1"]
//["val2","val2"]
//["val3","val3"]

如果不使用迭代器,而是使用回调方式,则可以调用集合的forEach()方法并传入回调,依次迭代每个键/值对。传入的回调参数接收可选的第二个参数,这个参数用于重写回调内部this的值:

const s=new Set(["val1","val2","val3"]);

s.forEach((val,dupVal)=>alert(`${val}->${dupVal}`));

//val1->val1
//val2->val2
//val3->val3

修改集合中值的属性不会影响其作为集合值的身份:

const s1=new Set(["val"]);

//字符串原始值作为值不会被修改
for (let value of s1.values()){
  value="newVal";
  alert(value);     //newVal
  alert(s1.has("val1"));  //true      
}

const valObj={id:1};
const s2=new Set([valObj]);

//修改值对象的属性,但对象仍然存在于集合中
for (let value of s2.values()){
  value.id="newVal";
  alert(value) ;          //{id:"newVal"} 
  alert(s2.has(valObj));     //true    
}
alert(valObj);         //{id:"newVal"}

//修改值对象的属性,但对象仍然存在于集合中
for(let value of s2.values()){
  values.id="newVal";
  alert(value); //{id:"newVal"}
  alert(s2.has(value)); //true
}
alert(valObj);       //{id:"newVal"}

四、定义正式集合操作

从各方面来看,Set跟Map都很相似,知识API稍有调整。唯一需要强调的就是集合API只支持自引用操作。很多开发者都喜欢使用Set操作,但需要手动实现;或者是子类化Set,或者是定义一个使用函数库。要把两种方式合二为一,可以在子类上实现静态方法,然后在实例方法中使用这些静态方法。在实现这些操作时,需要考虑几个地方。

1)某些Set操作是有关联性的,因此最好让实现的方法能支持处理任意多个集合实例。

2)Set保留插入顺序,所有方法返回的集合必须保证顺序。

3)尽可能高效地使用内存。扩展操作符的语法很简洁,但尽可能避免集合和数组间的相互转换能够节省对象初始化成为。

4)不要修改已有的集合实例。union(a,b)或a.union(b)应该返回包含结果的新集合实例。

class XSet extends Set{
  union(...sets){
       return XSet.union(this,...sets);
    }
  intersection(...sets){
       return XSet.intersection(this,...sets);  
    }
  difference(set) {
       return XSet.difference(this,set);
    }
  symmetricDifference(set){
       return  symmetricDifference(this,set)
    }
  cartesianProduct(set){
       return XSet.cartesianProduct(this,set);
  }
  powerSet(){
       return XSet.powerSet(this);
  }
  //返回两个或更多集合的并集
  static union(a,...bSets){
        const unionSet=new XSet(a);
        for (const b of bSets) {
           for (const bValue of b){
              unionSet.add(bValue);    
         }  
    } 
        return unionSet; 
    }
  //返回两个或更多集合的交集
  static intersection(a,...bSets){
     const intersectionSet=new XSet(a);
     for (const aValue of intersectionSet){
        for (const aValue of intersectionSet){
             if(!b.has(aValue){
                 intersectionsSet.delete(aValue);
              }
           }
        }  
     return differenceSet;
    }
  //返回两个集合的差集
  static difference(a,b){
     const differenceSet=new XSet(a);
     for (const bValue of b){
         if(a.has(bValue)){
             differenceSet.delete(bValue);
           }
       }
     return differenceSet;  
    }
  //返回两个集合的对称差集
  static symmetricDifference(a,b){
     //按照定义,对称差集可以表达为
     return a.union(b).difference(a.intersection(b));
  }
  
  //返回两个集合(数组对形式)的笛卡尔积
  //必须返回数组集合,因为笛卡尔积可能包含相同值的对
  static cartesianProduce(a,b){
     const cartesianProductSet=new XSet();
     for (const aValue of a){
        for (const bValue of b){
            cartesianProductSet.add([aValue,bValue])
           }
       }
     return cartesianProductSet;
  }
  //返回一个集合的幂集
  static powerSet(a){
     const powerSet=new XSet().add(new XSet());
     for (const aValue of a){
        for(const set of new XSet(powerSet)){
            powerSet.add(new XSet(set).add(aValue)); 
          }
       }
     return powerSet;
  }            
}

 

标签:Set,const,介绍,alert,add,集合,new,JS
来源: https://www.cnblogs.com/jaetyn/p/16411786.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有