js算法中常用数据结构-Set(集合)

126 阅读2分钟

1. 定义

Set是ES2015+出现的类似于类数组对象(arguements等)的数据结构,不同的是,它里面每个值都是唯一值,且可以包含任意类型的值。

在集合的规范中,查找集合的元素需要的时间和集合的元素个数呈现次线性关系(sublinear)。它可以代表任何算法复杂度低于O(N)的数据结构,如:hash表【O(1)】,查找树【O(log(N))】

❤❤❤❤❤性能

通过它的实例方法has查找一个值是否在集合中,速度比大多数数据结构要快。比如和数组长度相同的情况下,它的速度要比Array.prototype.includes要快。

2. 实例初始化

和数组,对象等的初始化一样,它也用new构建对象。初始化时,值必须可遍历,如数组、l类数组、字符串等。

const set = new Set();
const set = new Set([1,2,3,4]);
const set = new Set(document.querySelector("div"));
const set = new Set("hello");

⚡注意:

如果初始化的同时进行赋值,字符串类型需要注意。

const set = new Set("hello"); // 相当于插入5个字符, 但是里面有两个重复的
console.log(set) // 'h', 'e', 'l', 'o'

关于值是相等判断算法使用(sameValueZero),认为+0和-0相等,NaN和NaN相等。

3. 实例属性

size

const set = new Set("hello");
set.size; // 4

4. 实例方法

1.add(value)

const set = new Set();
set.add(1);

2.delete(value)

返回布尔值,删除成功返回true。

const set = new Set();
set.add("a");
set.delete("a"); // true

3.has(value)

const set = new Set();
set.add("a");
set.delete("a"); // true
set.has("a"); //false 

4.forEach(function(value){}[,this]))

const mySet2 = new Set([1, 2, 3, 4]);

mySet2.forEach((value) => {
  console.log(value); 
});
//1
//2
//3
//4

5.keys(),values()相同

返回值可以用for..of遍历,不可用forEach

6.entries()

返回数据类型Map

5. 可迭代属性

1. for...of

2. 和数组转换

// 转数组
const mySet = new Set([1,2,3,4]);
console.log([...mySet]); // [1,2,3,4]
console.log(Array.from(mySet)); // [1,2,3,4]

6. 实际应用

1. 数组去重

const myArr = [1,2,3,3,5,6,2,3,4];
console.log([...new Set(myArr)]); //[1,2,3,5,6,4]

2. 求交集

const setA = new Set([1,2,4,5,7,8,9]);
const setB = new Set([1,3,5,6,7,11,12]);
function intersection(setA, setB) {
    const _intersection = new Set();
    for(let ele of setA) {
        if (setB.has(ele)) {
            _intersection.add(ele);
        }
    }
    return _intersection;
}

3. 求合集

function union(setA, setB) {
    const _union = new Set(setB);
    for(let ele of setA){
         _union.add(ele);
    }
    return _union;
}

4.求对称差(合集-交集)

function symmetricDifference(setA, setB) {
    const _difference = new Set(setA); // 注意,必须再次实例化相当于copy,否则和对象类似
    for(let ele of setB) {
        if (setA.has(ele)) {// mdn上是_difference.has(ele)
            _difference.delete(ele);
        } else {
            _difference.add(ele)
        }
    }
    return _difference;
}

5. 判断子集

function isSuperset(set, subset) {
    for(const ele of subset) {
        if (!set.has(ele)) {
            return false;
        }
    }
    return true;
}

6. 判断差集(A有B没有)

function difference(setA, setB) {
    const _difference = new Set(setA); // 注意,必须再次实例化相当于copy,否则和对象类似
    for(let ele of setB) {
        if (setA.has(ele)) {// mdn上是_difference.has(ele)
            _difference.delete(ele);
        } 
    }
    return _difference;
}