JavaScript数据结构与算法(3)集合

主要参考:
https://www.cnblogs.com/xiaohuochai/p/8176248.html
《学习JavaScript数据结构与算法》

1.集合介绍

一个集合示例:

{1,2,3,4,5}

其实集合set内部是键值对方式:

在这里插入图片描述
集合这种键值对方式和字典很相似,集合是以[值,值]的形式存储元素,字典则是以[键,值]的形式来存储元素。

2.创建集合

声明一些集合可用的方法:
add(value):向集合添加一个新的项。
remove(value):从集合移除一个值。
has(value):如果值在集合中,返回true,否则返回false。
clear():移除集合中的所有项。
size():返回集合所包含元素的数量。与数组的length属性类似。
values():返回一个包含集合中所有值的数组。

代码实现如下:

function Set(){

	var items = {};

	//has(value)值是否在集合中,而且has方法会被下面调用
	this.has = function(value){
		return items.hasOwnProperty(value);
	}
	//add(value)添加值
	this.add = function(value){
		if(!this.has(value)){
			items[value] = value;
			return true; //表示执行到此结束,返回true,不然执行下面,返回false
		}
		return false;
	}

	//remove(value)
	this.remove = function(value){
		if(has(value)){
			delete items[value]; //delete 操作符用于删除对象{}/数组[]的某个属性;如果没有指向这个属性的引用,那它最终会被释放。
			return true;
		}
	}

	//clear(),移除集合中所有值,把一个空对象重新赋值给它
	this.clear = function(){
		items = {};
	}

	//size,一种方法是add或remove时length控制,下面是第二种方法
	this.size = function(){
		return Object.keys(items).length;
	}
	//sizeLegacy第三种方法,遍历items对象的每一个属性,记录属性的个数并返回这个数字。
	this.sizeLegacy = function(){
		var count = 0;
		for(var prop in items){
			if(items.hasOwnProperty(prop)){
				++count;
			}
		}
		return count;
	}

	//values 返回一个包含集合中所有值的数组,第一种方法,通过Object.keys()返回一个索引数组。
	this.values = function(){
		let values = [];
		let keys = Object.keys(items);

		for(let i=0;i<keys.length;i++){
			values.push(items[keys[i]]); //因为items是以对象形式,所以是[]形式
		}
		return values;

	}
	//values第二种方法,for in遍历可遍历对象,for in返回的是对象的每一个下标,还要记得使用hasOwenProperty()
	this.valuesLegacy = function(){
		let values1 = [];
		for(let key in items){
			if(items.hasOwnProperty(key)){
				values.push(items[keys])
			}
		}
		return values1;
	}

}

//测试Set类
var 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.remove(1); 
console.log(set.values()); //输出["2"]
set.remove(2); 
console.log(set.values()); //输出[]

3.集合操作

对集合可以进行如下操作
1、并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合
2、交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合
3、差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合
4、子集:验证一个给定集合是否是另一集合的子集

并集:

this.union = function(otherSet){

	//这里面用到了上面声明的new Set()、values()、add()

	//新的Set合集
	let unionSet = new Set();

	let values = this.values(); //this,获取当前示例的values(),即集合的数组形式
	for(let i=0;i<values.length;i++){
		unionSet.add(values[i]);
	}

	let values1 = otherSet.values();
	for(let i=0;i<values1.length;i++){
		unionSet.add(values1[i]);
	}

	return unionSet;

}

交集:

this.intersection = function(otherSet){

	let intersection = new Set();

	let values = this.values();
 
	for(let i=0;i<values.length;i++){
		if(otherSet.has(values[i])){
			intersection.add(values[i]);
		}
	}

	return intersection;

}

差集:

this.intersection = function(otherSet){
 let intersectionSet = new Set(); //{1}
 let values = this.values();
 for (let i=0; i<values.length; i++){ //{2}
  if (!otherSet.has(values[i])){ //{3}
    intersectionSet.add(values[i]); //{4}
  }
 }
 return intersectionSet;
}

子集:

this.subset = function(otherSet){
 if (this.size() > otherSet.size()){ //{1}
  return false;
 } else {
  let values = this.values();
  for (let i=0; i<values.length; i++){ //{2}
    if (!otherSet.has(values[i])){ //{3}
      return false; //{4}
    }
  }
  return true; //{5}
 }
};

4.完整代码

function Set() {

    let items = {};

    this.add = function(value){
        if (!this.has(value)){
            items[value] = value;
            return true;
        }
        return false;
    };

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

    this.has = function(value){
        return items.hasOwnProperty(value);
        //return value in items;
    };

    this.clear = function(){
        items = {};
    };

    /**
     * Modern browsers function
     * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
     * @returns {Number}
     */
    this.size = function(){
        return Object.keys(items).length;
    };

    /**
     * cross browser compatibility - legacy browsers
     * for modern browsers use size function
     * @returns {number}
     */
    this.sizeLegacy = function(){
        let count = 0;
        for(let key in items) {
            if(items.hasOwnProperty(key))
                ++count;
        }
        return count;
    };

    /**
     * Modern browsers function
     * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
     * @returns {Array}
     */
    this.values = function(){
        let values = [];
        for (let i=0, keys=Object.keys(items); i<keys.length; i++) {
            values.push(items[keys[i]]);
        }
        return values;
    };

    this.valuesLegacy = function(){
        let values = [];
        for(let key in items) {
            if(items.hasOwnProperty(key)) {
                values.push(items[key]);
            }
        }
        return values;
    };

    this.getItems = function(){
      return items;
    };

    this.union = function(otherSet){
        let unionSet = new Set(); //{1}

        let values = this.values(); //{2}
        for (let i=0; i<values.length; i++){
            unionSet.add(values[i]);
        }

        values = otherSet.values(); //{3}
        for (let i=0; i<values.length; i++){
            unionSet.add(values[i]);
        }

        return unionSet;
    };

    this.intersection = function(otherSet){
        let intersectionSet = new Set(); //{1}

        let values = this.values();
        for (let i=0; i<values.length; i++){ //{2}
            if (otherSet.has(values[i])){    //{3}
                intersectionSet.add(values[i]); //{4}
            }
        }

        return intersectionSet;
    };

    this.difference = function(otherSet){
        let differenceSet = new Set(); //{1}

        let values = this.values();
        for (let i=0; i<values.length; i++){ //{2}
            if (!otherSet.has(values[i])){    //{3}
                differenceSet.add(values[i]); //{4}
            }
        }

        return differenceSet;
    };

    this.subset = function(otherSet){

        if (this.size() > otherSet.size()){ //{1}
            return false;
        } else {
            let values = this.values();
            for (let i=0; i<values.length; i++){ //{2}
                if (!otherSet.has(values[i])){    //{3}
                    return false; //{4}
                }
            }
            return true;
        }
    };
}

ES6版本代码:

let Set2 = (function () {

    const items = new WeakMap();

    class Set2 {

        constructor () {
            items.set(this, {});
        }

        add(value){
            if (!this.has(value)){
                let items_ = items.get(this);
                items_[value] = value;
                return true;
            }
            return false;
        }

        delete(value){
            if (this.has(value)){
                let items_ = items.get(this);
                delete items_[value];
                return true;
            }
            return false;
        }

        has(value){
            let items_ = items.get(this);
            return items_.hasOwnProperty(value);
        }

        clear(){
            items.set(this, {});
        }

        size(){
            let items_ = items.get(this);
            return Object.keys(items_).length;
        }


        values(){
            let values = [];
            let items_ = items.get(this);
            for (let i=0, keys=Object.keys(items_); i<keys.length; i++) {
                values.push(items_[keys[i]]);
            }
            return values;
        }

        getItems(){
            return items.get(this);
        }

        union(otherSet){
            let unionSet = new Set();

            let values = this.values();
            for (let i=0; i<values.length; i++){
                unionSet.add(values[i]);
            }

            values = otherSet.values();
            for (let i=0; i<values.length; i++){
                unionSet.add(values[i]);
            }

            return unionSet;
        }

        intersection(otherSet){
            let intersectionSet = new Set();

            let values = this.values();
            for (let i=0; i<values.length; i++){
                if (otherSet.has(values[i])){
                    intersectionSet.add(values[i]);
                }
            }

            return intersectionSet;
        }

        difference(otherSet){
            let differenceSet = new Set();

            let values = this.values();
            for (let i=0; i<values.length; i++){
                if (!otherSet.has(values[i])){
                    differenceSet.add(values[i]);
                }
            }

            return differenceSet;
        };

        subset(otherSet){

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

5.ES6中集合

ECMAScript 2015新增了Set类。我们可以基于ES6的Set开发我们的Set类

和我们的Set不同,ES6的Set的values方法返回Iterator,而不是值构成的数组。另一个区别是,我们实现的size方法返回set中存储的值的个数,而ES6的Set则有一个size属性:

let set = new Set([1,2,3,2,4,5,6,7])

set.has(1)
true

set.size
8

在这里插入图片描述

可以用delete方法删除set中的元素:

set.delete(1)
true

clear方法会重置set数据结构,这跟我们实现的功能一样

set.clear()
undefined

set
Set(0) {}

ES6中的集合

let set = new Set();

//--------- Union ----------
let unionAb = new Set();
for (let x of setA) unionAb.add(x);
for (let x of setB) unionAb.add(x);

//--------- Intersection ----------
let intersection = function(setA, setB){
    let intersectionSet = new Set();

    for (let x of setA){
        if (setB.has(x)){
            intersectionSet.add(x);
        }
    }

    return intersectionSet;
};
let intersectionAB = intersection(setA, setB);
//alternative - works on FF only
//intersectionAb = new Set([x for (x of setA) if (setB.has(x))]);

//--------- Difference ----------
let difference = function(setA, setB){
    let differenceSet = new Set();

    for (let x of setA){
        if (!setB.has(x)){
            differenceSet.add(x);
        }
    }

    return differenceSet;
};
let differenceAB = difference(setA, setB);
//alternative  - works on FF only
//differenceAB = new Set([x for (x of setA) if (!setB.has(x))]);

更详细可以参考上面链接和书籍。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页

打赏

Cacra

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者