JS Set 集合

Java中集合框架

集合(Set)是由一组无序且唯一(即不能重复)的项组成的数据结构,它使用了与有限集合相同的数学概念。可将它想象成是一个即没有重复元素,也没有排序顺序概念的数组。

  • 集合是一种包含不同元素的数据结构
  • 集合中的元素称为成员
  • 集合中的成员是无序的
  • 集合不允许相同成员存在

集合的相关概念

集合的数学概念

  • 空集,表示不包含任何元素的集合。如24和29之间的素数集合。
{}
  • 一个由大于或等于0的整数组成的自然数集合
N = {0, 1, 2, 3, 4, 5, 6...}

集合的相关概念

  • 不包含任何成员的集合称为空集,全集则是包含一切可能成员的集合。
  • 若两个集合的成员完全相同则成两个集合相等
  • 若一个集合中所有成员都属于另一个集合,则前一个集合称为后一集合的子集。

小结:集合是由一组无序但彼此之间又有一定相关性的成员构成的,每个成员在集合中只能出现一次。

  • 集合中的成员的顺序是任意的或其他任意形式的组合
  • 集合必须保证每个成员只能出现一次

集合的基本操作

集合操作

对集合的基本操作分为

  • 交集(intersect):两个集合中共同存在的成员组成一个新集合
  • 并集(union):将两个集合中的成员进行合并后得到一个新集合
  • 补集/差集(subtract):属于一个集合而不属于另一个集合的成员组成的集合
  • 子集(subset):验证一个给定集合是否是另一个集合的子集

集合的实现

目前的JS实现已经是基于2011年6月发布的ECMAScript5.1(现代浏览器均已支持),包括了Array类的实现。ECMAScript6(ECMAScript2015,2015年6月发布)包括了Set类的实现。

基于数组实现Set类

/*基于数组实现的集合类*/
function Set(){
    this.data = [];//存放数据
    /*集合的增删改查*/
    this.add = add;
    this.remove = remove;
    this.show = show;
    this.size = size;
    /*集合的专属操作*/
    this.contains = contains;
    this.union = union;
    this.intersect = intersect;
    this.subset = subset;
    this.difference = difference;
}

/**将数据存储到集合:集合中不能包含相同元素*/
function add(element){
    //检查新加入的元素在数组中是否存在
    var pos = this.data.indexOf(element);
    if(pos < 0){
        //将新增元素追加到数组末尾
        this.data.push(element);
        return true;
    }else{
        return false;
    }
}
/*从集合中删除指定数据*/
function remove(element){
    //检查待删除元素是否存在数组中
    var pos = this.data.indexOf(element);
    if(pos > -1){
        //删除数组元素
        this.data.splice(pos, 1);
        return true;
    }else{
        return false;
    }
}
/*显示集合成员*/
function show(){
    return this.data;
}
/*显示集合成员个数*/
function size(){
    return this.data.length;
}
/*检查一个成员是否属于该集合*/
function contains(element){
    var pos = this.data.indexOf(element);
    return pos > -1;
}
/*并集操作:将两个集合合并成一个*/
function union(set){
    //将第一个集合的成员悉数加入到一个临时集合中
    var tmpset = new Set();
    for(var i=0; i<this.data.length; ++i){
        tmpset.add(this.data[i]);
    }
    //检查第二个集合中的成员是否同时属于第一个集合,若属于则跳过否则加入临时集合
    for(var i=0; i<set.data.length; ++i){
        if(!tmpset.contains(set.data[i])){
            tmpset.add(set.data[i]);
        }
    }
    //返回临时集合
    return tmpset;
}
/*求两个集合的交集*/
function intersect(set){
    var tmpset = new Set();
    for(var i=0; i<this.data.length; ++i){
        if(set.contains(this.data[i])){
            tmpset.add(this.data[i]);
        }
    }
    return tmpset;
}
/*是否子集*/
function subset(set){
    //确定该集合的长度是否小于待比较集合
    if(this.size() > set.size()){
        return false;
    }else{
        //判断该集合内的成员是否都属于待比较集合
        for each(var member in this.data){
            if(!set.contains(member)){
                return false;
            }
        }
    }
    return true;
}
/*集合补集:属于第一个集合但不属于第二个集合的成员*/
function difference(set){
    var tmpset = new Set();
    for(var i=0; i<this.size(); ++i){
        if(!set.contains(this.data[i])){
            tmpset.add(this.data[i]);
        }
    }
    return tmpset;
}
/*test*/
var it = new Set();
it.add('jennifer');
it.add('john');
it.add('clayton');
it.add('alice');

var cis = new Set();
cis.add('alice');
cis.add('bryan');
cis.add('clayton');
cis.add('danny');

var union = new Set();
union = it.union(cis);
print(union.show());//jennifer,john,clayton,alice,bryan,danny

var inter = it.intersect(cis);
print(inter.show());//clayton,alice

print(it.subset(union));//true

var diff = new Set();
diff = it.difference(cis);
print(diff.show());//jennifer,john

基于数组实现集合操作


/*集合交集*/
Array.intersection = function(){
    var arr = [], obj = {};
    for(var i=0; i<arguments.length; i++){
        for(var j=0; j<arguments[i].length; j++){
            var ele = arguments[i][j];
            if(!obj[ele]){
                obj[ele] = 1;
            }else{
                obj[ele]++;
                if(obj[ele] == arguments.length){
                    arr.push(ele);
                }
            }
        }
    }
    return arr;
};
/*数组并集*/
Array.union = function(){
    var arr=[], obj={};
    for(var i=0; i<arguments.length; i++){
        for(var j=0; j<arguments[i].length; j++){
            var ele = arguments[i][j];
            if(!obj[ele]){
                obj[ele] = 1;
                arr.push(ele);
            }
        }
    }
    return arr;
};

/*集合去重*/
Array.prototype.unique = function(){
    var arr = [], obj = {};
    for(var i=0,j=this.length; i<j; i++){
        if(!obj[this[i]]){
            obj[this[i]] = 1;
            arr.push(this[i]);
        }
    }
    return arr;
}

/*集合差集*/
Array.prototype.subtract = function(ary){
    var arr = [], obj = {};
    for (var i = 0; i < ary.length; i++) {
        obj[ary[i]] = 1;
    }
    for (var j = 0; j < this.length; j++) {
        if (!obj[this[j]]){
            obj[this[j]] = 1;
            arr.push(this[j]);
        }
    }
    return arr;
}
/*test*/
//print(Array.intersection([1,2,3],[1,2,4]));//1,2
// print([1,2,3,4,1,2,3].unique());//1,2,3,4

// print(Array.union([1,2],[2,3],[3,4]));//1,2,3,4
// print([1,2,3,4,5,6].subtract([1,3,9,8]));//2,4,5,6

基于对象实现Set类

使用对象而非数组来表示集合(items),JS的对象不允许一个键指向两个不同的属性,保证了集合中的元素都是唯一的。

集合类的抽象数据类型

  • add(value) 向集合中添加一个新项
  • remove(value) 从集合中移除一个值
  • has(value) 判断值是否存在集合中,存在返回true,不存在返回false。
  • clear() 移除集合中所有项
  • size() 获取集合中所包含元素的数量
  • values() 获取包含集合汇总所有值的数组
function Set(){
    var items = {};
    /*判断值是否存在集合中*/
    this.has = function(value){
        //return value in items;
        //所有JS对象均有hasOwnProperty方法,它返回一个表明对象是否具有特定属性的布尔值。
        return items.hasOwnProperty(value);
    };
    /*向集合中添加新值*/
    this.add = function(value){
        if(!this.has(value)){
            //添加新值时将其同时作为键和值保存有利于查找
            items[value] = value;//将新值添加到集合中
            return true;
        }
        return false;
    };
    /*从集合中移除某值*/
    this.remove = function(value){
        if(this.has(value)){
            delete items[value];//从对象中移除属性
            return true;
        }
        return false;
    };
    /*从集合中移除所有值*/
    this.clear = function(){
        items = {};//使用空对象赋值即可
    };
    /*获取集合所包含元素的个数*/
    this.size = function(){
        //return Object.keys(items).length;//IE9+、FF4、Chrome5+、Opera12+、Sarafi5+
        var count = 0;
        for(var prop in items){
            //检查是否为对象自身属性,因为对象的原型会包含了额外的属性,以避免重复计数。
            if(items.hasOwnProperty(prop)){
                ++count;
            }
        }
        return count;
    };
    /*获取包含集合所有值的数组*/
    this.values = function(){
        // return Object.keys(items);//IE9+、FF4、Chrome5+、Opera12+、Sarafi5+
        var keys = [];
        for(var key in items){
            keys.push(key);
        }
        return keys;
    };

    /*交集:元素同时存在两个不同的集合中*/
    this.intersection = function(set){
        var tmpset = new Set();
        var values = this.values();
        for(var i=0; i<values.length; i++){
            if(set.has(values[i])){
                tmpset.add(values[i]);
            }
        }
        return tmpset;
    };
    /*并集*/
    this.union = function(set){
        var tmpset = new Set();
        var values = this.values();
        for(var i=0; i<values.length; i++){
            tmpset.add(values[i]);
        }
        values = set.values();
        for(var i=0; i<values.length; i++){
            tmpset.add(values[i]);
        }
        return tmpset;
    };
    /*差集*/
    this.difference = function(set){
        var tmpset = new Set();

        var values = this.values();
        for(var i=0; i<values.length; i++){
            if(!set.has(values[i])){
                tmpset.add(values[i]);
            }
        }

        return tmpset;
    };
    /*子集*/
    this.subset = function(set){
        if(this.size() > set.size()){
            return false;
        }else{
            var values = this.values();
            for(var i=0; i<values.length; i++){
                if(!set.has(values[i])){
                    return false;
                }
            }
            return true;
        }
    };
}
/*test*/
var set = new Set();
set.add(1);
print(set.values(), set.has(1), set.size());//1 true 1

set.remove(1);
print(set.values(), set.has(1), set.size());// false 0
集合操作
/*test*/
var setA = new Set();
setA.add(1);
setA.add(2);
setA.add(3);

var setB = new Set();
setB.add(1);
setB.add(2);
setB.add(4);

var inter = setA.intersection(setB);
var union = setA.union(setB);
var diff = setA.difference(setB);
var subset = setA.subset(setB);

print(inter.values());//1,2
print(union.values());//1,2,3,4
print(diff.values());//3
print(subset);//false
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • Java集合框架 Java中封装了许多常用的数据结构,称为集合框架,可以有效组织数据,提高程序性能。最初Java只...
    Steven1997阅读 933评论 0 2
  • 愉快的假期告一段落,继续我们的学习~ 集合(Set) 同数学中所学的一样,集合(Set)是由一组无序但彼此之间又有...
    Cryptic阅读 6,677评论 4 8
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,378评论 0 4
  • 听听海边的风,沙子在我脚下流动 月亮从夜幕中浮起 潮水在暗涌 漂亮的贝壳已经被人拾去 我只能捧起这湿润的沙 装在旧...
    钟子明阅读 366评论 6 3
  • 佩奇排名(PageRank),又称网页排名、谷歌左侧排名,是一种由搜索引擎根据网页之间相互的超链接计算的技术,而作...
    Nicky_Ye阅读 20,956评论 1 12