乐趣区

JavaScript数据结构与算法五集合

集合是由一组无序且唯一 (不能重复) 的项组成的,与我们高中数学学的集合同样具有有限性,
这种数据结构大多数用来存储唯一元素。

集合

创建集合类

class Set {constructor() {this.items = {};
  }

检验某个元素是否存在集合中。

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

添加元素

add(element) {if (!this.has(element)) {this.items[element] = element;// 把键和值保存,有利于查找该元素
      return true;
    }
    return false;
  }

删除和清空操作

delete(element) {if (this.has(element)) {delete this.items[element];
      return true;
    }
    return false;
  };
clear() {this.items = {};
  };

返回集合中有多少个元素

size() {return Object.keys(this.items).length;
  };
// 另外一种方式
/*
sizeLegacy(){
    let count = 0;
    for(let key in this.items){if(this.items.hasOwnProperty(key)){// 判断是否是对象的属性,避免重复计数
        count++;
      }
      return count;
    };
  }
*/

返回对象所有属性值的数组

valuesLegacy(){let values = [];
    for(let key in this.items){if(this.items.hasOwnProperty(key)){values.push(key);
      };
    };
    return values;
  }
// 另一种写法,只适用于现代浏览器
values() {return Object.values(this.items);
  }

以上就是集合数据结构的创建和成员函数的添加。而集合最主要的是它的运算,在计算机领域中应用最多的是数据库,发送一条 SQL 查询命令时,使用的是集合运算,返回的也是数据集合。接下来介绍相对常见的集合运算(以下代码引用 ES6 语法)

集合运算

并集

union(otherSet) {const unionSet = new Set();
    this.values().forEach(value => unionSet.add(value));
    otherSet.values().forEach(value => unionSet.add(value));
    return unionSet;
  }

交集

intersection(otherSet) {const intersectionSet = new Set();
    const values = this.values();
    const otherValues = otherSet.values();
    let biggerSet = values;
    let smallerSet = otherValues;
    if (otherValues.length - values.length > 0) {
      biggerSet = otherValues;
      smallerSet = values;
    }
    smallerSet.forEach(value => {if (biggerSet.includes(value)) {intersectionSet.add(value);
      }
    });
    return intersectionSet;
  }

差集

difference(otherSet) {const differenceSet = new Set();
    this.values().forEach(value => {if (!otherSet.has(value)) {differenceSet.add(value);
      }
    });
    return differenceSet;
  }

判断当前集合是不是被检测的集合的子集

isSubsetOf(otherSet) {if (this.size() > otherSet.size()) {return false;}
    let isSubset = true;
    this.values().every(value => {if (!otherSet.has(value)) {
        isSubset = false;
        return false;
      }
      return true;
    });
    return isSubset;
  }

以上是我们实现的集合运算,但是 ES2015 原声的 Set 并没有这些功能,如果有需要的话,我们也可以模拟。

模拟运算

模拟并集运算

const union = (set1, set2) => {const unionAb = new Set();
  set1.forEach(value => unionAb.add(value));
  set2.forEach(value => unionAb.add(value));
  return unionAb;
};
// 第二种:使用拓展运算符
new Set([...setA, ...setB]);

模拟交集运算

const intersection = (set1, set2) => {const intersectionSet = new Set();
  set1.forEach(value => {if (set2.has(value)) {intersectionSet.add(value);
    }
  });
  return intersectionSet;
};
// 第二种:使用拓展运算符
new Set([...setA].filter(x => setB.has(x)))

模拟差集运算

const difference = (set1, set2) => {const differenceSet = new Set();
  set1.forEach(value => {if (!set2.has(value)) {differenceSet.add(value);
    }
  });
  return differenceSet;
};
// 第二种:使用拓展运算符
new Set([...setA].filter(x => !setB.has(x)))
退出移动版