实现JavaScript基本数据结构系列---集合Set

182 阅读2分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

集合Set

集合是一组无序且唯一(不能重复)的项组成中,和ES2015中的Set类一样,这种数据结构使用了与有限集合相同的数学概念。我们会实现一个Set类,以及实现简单的交并差集计算。和Map不同的是,Set集合是一种“值-值”的对象。

创建集合类

用什么来存数据呢,数组还是对象?这里我们用对象,因为对象不允许一个键指向两个值,也就保证了集合里的元素是唯一的。那他需要哪些方法呢?

  1. add(element): 像集合添加一个元素
  2. delete(element): 像集合移除一个元素
  3. has(element): 集合中是否存在某个元素
  4. clear(): 移除集合中所有元素
  5. size(): 返回集合中所有的元素
  6. values(): 返回包含集合中所有元素的数组
class Set {
    constructor() {
        this._value = {};
    }
    add(element) {
        if (this.has(element)) return false;

        this._value[element] = element;
        return true;
    }

    delete(element) {
        if (!this.has(element)) return false;

        delete this._value[element];
        return true;
    }

    has(element) {
        return Object.prototype.hasOwnProperty.call(this._value, element)
    }

    clear() {
        this._value = {};
    }

    size() {
        return Object.keys(this._value).length;
    }

    values() {
        return Object.keys(this._value);
    }

}

并集

对于给定的两个集合,返回一个包含两个集合所有元素的新集合

// 并集
union(otherSet) {
    const result = new Set();
    this.values().forEach(element => result.add(element));
    otherSet.values().forEach(element => result.add(element));

    return result;
}

交集

对于给定的两个集合,返回一个包含两个集合共有元素的新集合

// 交集
interSection(otherSet) {
    const result = new Set();
    this.values().forEach(element => {
        if (otherSet.has(element)) {
            result.add(element)
        }
    });
    return result;
}

差集

对于给定的两个集合,返回一个包含所有在第一个集合而不在第二个集合中的元素的新集合

// 差集
difference(otherSet) {
    const result = new Set();
    this.values().forEach(element => {
        if (!otherSet.has(element)) {
            result.add(element)
        }
    });
    return result;
}

子集

验证一个给定集合是否是另一个集合的子集

// 子集
isSubSet(otherSet) {
    if (this.size() > otherSet.size()) return false;

    const values = this.values();
    for (let i = 0; i < this.size(); i++) {
        if (!otherSet.has(values[i])) {
            return false
        }
    }
    return true;
}

测试用例

const setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)

const setB = new Set()
setB.add(1)
setB.add(2)
setB.add(3)
setB.add(4)
setB.add(5)

console.log(setA.union(setB).values()); // 并集 1,2,3,4,5
console.log(setA.interSection(setB).values()); // 交集 1, 2, 3
console.log(setA.difference(setB).values()); // 差集 【】
console.log(setA.isSubSet(setB)); // 子集 true