集合-基本实现

集合是由一组无序且唯一(即不能重复)的项组成的一种结构.

该数据结构使用了与有限集合相同的数学概念.

基于的操作基本围绕并集, 交集, 差集等展开. 多的就不讲了, 基本的数学常识还是具备的. 我用集合用得比较多的地方就是在做一些数据统计, 数据拆分等会用到.

创建集合

这里我们底层用 js 对象来实现, 用对象有个好处是它的键天然就是要求唯一的, 比较好操作. 当然用数组也行, 只是操作没有那么方便, 但也能搞.

class Set {
  constructor() {
    // 这里用对象来实现集合, key 唯一比较方便
    this.obj = {} 
  }

集合方法

  • add(element):向集合添加一个新元素
  • delete(element):从集合移除一个元素
  • has(element):如果元素在集合中,返回true,否则返回false。
  • clear():移除集合中的所有元素。
  • size():返回集合所包含元素的数量。它与数组的length属性类似。
  • values():返回一个包含集合中所有值(元素)的数组。

元素是否在集合中

底层是用对象来存储元素, 直接用 in 运算符即可, 但更推荐用 hasOwnProperty() 方法.

  • in : 属性会查找实例本身 + 原型链
  • hasOwnProperty() : 仅限于实例本身
has(element) {
    return Object.prototype.hasOwnProperty.call(this.obj, element)
}

这里不直接用 obj.hasOwnProperty(key) 的原因是并非所有对象都集成了 Object.prototype. 直接用可能导致异常, 所以才用原型链 + call 改变 this 指向 的方式来稳一手.

添加元素

要先判断元素是否已在集合中, 不在才能添加, 再就返回 false 啦.

add(element) {
    if (! this.has(element)) {
        this.obj[element] = element
        return true
    }
    return false
}

删除元素

  • 删除一项
  • 删除全部
delete(element) {
    if (this.has(element)) {
        // 底层是对象, 可以直接用 delete
        delete this.obj[element]
        return true
    }
    return false
}

clear() {
    this.obj = {}
}

集合大小

  • 定义一个 length 变量, 每次 add, delete 时进行控制
  • ES6: Object.keys(obj).length
  • 对象属性遍历
// 方法3实现
size() {
    let count = 0
    for (let key in this.obj) {
        if (this.obj.hasOwnProperty(key)) count++
    }
    return count
}

集合元素列表

  • ES6: Object.values(obj) 返回对象值组成的数组
  • 对象属性遍历
values() {
	let arr = []    
    for (let key in this.obj) {
        if (this.obj.hasOwnProperty(key)) {
            arr.push(key)
        }
    }
    return arr
}

完整实现

class Set {
  constructor() {
    // 这里用对象来实现集合, key 唯一比较方便, 当然也可以用数组
    this.obj = {} 
  }

  // 查询元素是否在集合中
  has(element) {
    // return element in this.obj 
    return Object.prototype.hasOwnProperty.call(this.obj, element)
  }

  // 添加元素
  add(element) {
    if (! this.has(element)) {
      this.obj[element] = element
      return true
    }
    return false 
  }

  // 删除元素
  delete(element) {
    if (this.has(element)) {
      // 能用 delete 是因为底层用的是对象
      delete this.obj[element]
      return true 
    }
    return false 
  }

  // 清空集合
  clear() {
    this.obj = {}
  }

  // 集合元素个数
  size() {
    // 方法1: 使用一个 count 变量, 每次新增/删除时进行控制
    // 方法2: 用 ES6 语法, Object.keys().length 返回键组成的数组
    // return Object.keys(this.obj).length

    // 方法3: 手动提取底层对象的属性进行计数
    let count = 0
    for (let key in this.obj) {
      // in 会包含原型链上的, hasOwnProperty() 只查找实例自身的
      if (this.obj.hasOwnProperty(key)) count++
    }
    return count 
  }

  // 返回集合元素值
  values() {
    // 方法1: 用 ES6, Object.values() 返回值组成的数组
    // return Object.values(this.obj)

    // 方法2: 遍历对象 key 都存起来
    let arr = []
    for (let key in this.obj) {
      if (this.obj.hasOwnProperty(key)) arr.push(key)
    }
    return arr 
  }
}

测试:

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

console.log(set.values()); // 输出[1]
console.log(set.has(1)); // 输出true
console.log(set.size()); // 输出1

set.add(2);
console.log(set.values()); // 输出[1, 2]
console.log(set.has(2)); // 输出true
console.log(set.size()); // 输出2

set.delete(1);
console.log(set.values()); // 输出[2]

set.delete(2);
console.log(set.values()); // 输出[]

关于集合的基本实现思路就到这里啦.

posted @ 2024-06-14 21:21  致于数据科学家的小陈  阅读(11)  评论(0编辑  收藏  举报