首页 文章 精选 留言 我的

精选列表

搜索[国密算法],共10000篇文章
优秀的个人博客,低调大师

JS中的算法与数据结构——集合(Set)

集合(Set) 同数学中所学的一样,集合(Set)是由一组无序但彼此之间又有一定关系性的成员构成,每个成员在集合中只能出现一次,它是一种包含了不同元素的数据结构(集合中的元素称为成员),从其定义中我们可以看出它具有两个很重要的特征:首先,集合中的成员是无序的,其次,集合中的成员是不相同的,即集合中不存在相同的成员。 实际上,很多编程语言中,集合并不是一种数据类型,但是如果你需要创建一个数据结构用来保存一些独一无二的元素时,集合就变得很有用了,接下来我们一起来看看JS中如何实现一个集合。 集合的定义 我们要实现一个集合,首先要对其一些定义做了解 不包含任何成员的集合称为空集,包含一切可能成员的集合称为全集。 如果两个集合里的成员都完全相同,则称两个集合相等。 如果一个集合所有成员都包含于另一个集合,则前一集合称为后一集合的一个子集。 集合的操作 通常来说,集合的基本操作有以下三种: 并集:将两个集合中的成员进行合并,得到一个新的集合 交集:将两个集合中共同存在的成员组成的一个新的集合 补集:属于一个集合而不属于另一个集合的成员组成的新的集合 集合的实现 集合(Set)的实现我们这里基于数组,用数组来存储数据,根据我们之前学习的以及上面提到的一些方法,我们可以将集合的构造函数定义如下(为了区别ES6的 set 类型,我们这里选择用 MySet 命名): //构造函数 function MySet () { this.dataStore = []; // 数据存储 this.add = add; // 添加成员 this.remove = remove; // 删除成员 this.size = size; // 集合元素个数 this.union = union; // 集合求并集 this.intersect = intersect; // 集合求交集 this.subset = subset; // 判断一个集合是否是另一集合的子集 this.difference = difference; // 集合求补集 this.contains = contains; // 判断某成员是否属于该集合 this.show = show; // 显示当前集合 } 复制代码 我们第一个要实现的方法就是向集合中添加一个成员,即 add 方法 add:向集合中添加一个成员 //添加元素 function add (data) { //判断元素是否存在集合当中 if( this.dataStore.indexOf( data ) < 0 ){ this.dataStore.push(data); return true; }else{ console.warn( 'Can not add ' + data + ', must already be in set'); return false; } } 复制代码 我们之前提到,集合中的元素是独一无二的,因此,我们在将数据存储到数组之前,首先就是要确保该集合不存在该数据,因此,我们先用 indexOf 方法检查新加入的元素是否存在,如果找到了就返回该成员在数组中的位置;否则,就返回 -1 ,那么对应的 add 方法就可以定义返回布尔值,添加成功我们返回 true , 否则返回 false ,这样就可以明确告诉我们是否正确的插入了一个元素。 remove:删除集合中某个成员 //删除元素 function remove (data) { //判断元素是否存在集合当中 var pos = this.dataStore.indexOf(data); if( pos > -1 ){ this.dataStore.splice(pos,1); return true; }else{ console.warn( data + ' is not in set'); return false; } } 复制代码 这里,我们顺理成章的实现了删除方法,它跟 add 方法很类似,首先要检查待删除元素是否存在于数组中,如果存在,我们调用数组的 splice() 方法删除该元素并返回 true ,否则,直接返回 false ,表示集合中不存在该元素。 现在,我们可以完成集合的添加和删除,要测试这些方法之前,我们首先得定义 show 方法,该方法用来显示集合中的成员,该方法的实现很简答,只需返回我们定义的数组即可: show:显示集合中的成员 // 显示集合成员 function show(){ console.log(this.dataStore); return this.dataStore; } 复制代码 接着,我们这会来测试一下: var fruits = new MySet(); // 添加成员 fruits.add('Apple'); fruits.add('Banana'); fruits.add('Pear'); fruits.show(); // ["Apple", "Banana", "Pear"] // 添加重复成员 fruits.add('Apple'); // Can not add Apple, must already be in set // 删除成员 fruits.remove('Banana'); fruits.show(); // ["Apple", "Pear"] // 删除不存在的成员 fruits.remove('Banana'); // Banana is not in set 复制代码 嗯,一切正常,我们可以来实现集合的一些高级操作了,我们先来看看 union (并集)的实现。 union:求集合并集 求集合的并集,就是要将两个集合合并成一个,并除去重复的元素,我们实现思路就是将第一个集合成员放到一个临时集合中,判断第二个集合的成员是否也属于第一个集合,如果为真,代表为重复元素,我们直接跳过该成员,否则将该成员加入临时集合,最后返回该集合即可; 那么,问题来了,我们要如何判断一个成员是否存在于该集合中?因此,我们需要一个辅助方法 contains(),它的实现也非常简单,直接用 indexOf 判断即可 //判断元素是否属于该集合 function contains (data) { if( this.dataStore.indexOf(data) > -1 ){ return true; }else{ return false; } } 复制代码 现在,我们可以定义 union 方法了 //求集合的并集 function union ( set ) { var tempSet = new MySet(); for( var i = 0 ; i < this.dataStore.length ; i++ ){ tempSet.add(this.dataStore[i]); } for( var i = 0 ; i< set.dataStore.length ; i++ ){ if( !tempSet.contains(set.dataStore[i])){ tempSet.dataStore.push(set.dataStore[i]); } } return tempSet; } 复制代码 这样,我们就可以就集合的并集了, var fruits1 = new MySet(); fruits1.add('Apple'); fruits1.add('Banana'); fruits1.add('Pear'); var fruits2 = new MySet(); fruits2.add('Grape'); fruits2.add('Banana'); fruits2.add('Pear'); fruits2.add('Orange'); var union = fruits1.union( fruits2 ); union.show(); // ["Apple", "Banana", "Pear", "Grape", "Orange"] 复制代码 成功了!我们可以来看看求集合的交集了。 intersect:求集合的交集 有了上面求并集的思路,那么交集的定义来说也相对简单,思路就是发现第一个集合的成员也属于第二个集合时,就将该成员加入到新的集合,最后返回新的集合即可; //求集合的交集 function intersect (set) { var tempSet = new MySet(); for(var i = 0 ; i < this.dataStore.length ; i++ ){ if( set.contains(this.dataStore[i])){ tempSet.add(this.dataStore[i]); } } return tempSet; } 复制代码 我们还是利用上面的两个集合接着求其交集: var intersect = fruits1.intersect( fruits2 ); intersect.show(); // ["Banana", "Pear"] 复制代码 下一个定义的操作是 subset ; subset:判断集合是否是另一集合的子集 该方法首先要确定 该集合的长度是否小于待比较的集合。如果该集合比待比较集合还要大,那么肯定不是待比较集合的一个子集。只要当,待比较集合比较大时,才去判断集合类的成员是否都属于待比较集合,如果有一个不是,直接返回 false , 只有当所有元素都属于待比较集合的时候,我们才能说该集合是待比较集合的一个子集,该方法才会返回 true , 为了方便查看,我加入了console打印; //子集判断 function subset (set) { if( this.size() > set.size() ){ console.log('not a subset'); return false; }else{ for ( var i = 0 ; i < this.dataStore.length ; i++ ){ if( !set.contains(this.dataStore[i])){ console.log('not a subset'); return false; } } } console.log(' a subset'); return true; } 复制代码 我们看到上面用到了 size 方法,它的定义如下: //返回集合长度 function size () { return this.dataStore.length; } 复制代码 我们保留上面的 fruits1 和 fruits2 , 新建一个 fruits3 来演示 subset 方法 var fruits3 = new MySet(); fruits3.add('Apple'); fruits3.add('Banana'); fruits3.add('Pear'); fruits3.add('Grape'); fruits3.add('Orange'); //子集判断 fruits1.subset( fruits2 ); // not a subset fruits2.subset( fruits2 ); // a subset fruits1.subset( fruits3 ); // a subset 复制代码 看起来一切都很顺利,我们只剩最后一个 difference 方法,该方法返回一个新集合,该集合是由属于第一个集合而不属于第二个集合的成员组成的。 difference:补集 有了交集的思路,补集的实现就显得很自然了。 //补集 function difference (set) { var tempSet = new MySet(); for( var i = 0 ; i < this.dataStore.length ; i ++ ){ if( !set.contains(this.dataStore[i])){ tempSet.dataStore.push( this.dataStore[i] ); } } return tempSet; } 复制代码 我们测试一下: fruits1.difference(fruits2).show(); // ['Apple'] fruits1.difference(fruits3).show(); // [] fruits2.difference(fruits1).show(); // ["Grape", "Orange"] 复制代码 到现在,我们完成了一个完整的 set 集合! 本篇介绍的集合和 ES6 的集合略微有点差别,ES6 提供的 Set 数据结构,有很多现成的方法可以直接调用获~ 如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star: http://github.crmeb.net/u/defu 不胜感激!

优秀的个人博客,低调大师

大数据之路 ——(一)算法建模中的数据清洗

作者:Mochou 来源:恒生LIGHT云社区 在当前大数据的背景下,数据处理占了极大的份额,就像一个西红柿做成西红柿炒鸡蛋,需要经过调料整合,菜料清洗,饭菜加工等等才能发布到生产,不,发送到餐桌。 这里简单分享一下我对数据清洗的理解,其具有很重要的地位,不然面对着脏乱差的西红柿炒鸡蛋,没人愿意下口。 一份未经清洗过的数据一般会存在这些不符合分析要求的问题:比如重复,错误,空值,异常数据等,对于错误数据,因为是业务源头问题,比如性别明明是男却成了女,这些我们无法处理,只能从源端进行规范,就像顾客想吃河南的西红柿,厨房里进的只有山东的,这个厨师没办法解决,只能通知进货商更改。故我们只对另外三个问题进行清洗修改,必须申明一点,所有的清洗都要基于实际业务来做,比如重复,可能业务要的就是重复,你给人家洗掉了,就产生了问题 一 . 重复 如果实际业务不要重复值,重复值可以直接删除,比如数据库里可以在整合合并时用union而不是union all ,不支持union的可以用主键分组排序取第一个 row_number() over (partition by .. order by..desc) as.. 如果也不支持row_number,,,那好好活着吧。 其他语言也都有类似的去重函数,如python可以直接用drop_duplicates() 二 . 缺失 缺失也就是空值,需要明确一点,‘空’有两种情况,一种是真正的对象为空,即null,一种是空值,即xxx='',所以我们处理这些空值时需要分两种情况,一种是xxx is null, 一种是length(trim(xxx))=0。 空值处理一般是填补,这个根据实际业务需要来做,一般来讲, 空值数量比较小时可以填补上连续值的某一个,比如平均数,中位数等; 空值较多时,占了五成以上,可以考虑使用众数来填补; 空值占了绝大部分,这个时候就没必要再用原有的数据,可以自己造数据,生成一个指示哑变量,参与后续的建模需要。 前面已经说过在数据库里怎么处理,这里说下在python里如何处理 # 列出空值在每个列所占的比重 # df是数据集,col.size是当前数据的行数 df.apply(lambda col:sum(col.isnull())/col.size) # 用均值填补,使用pandas包里的fillna df.col1.fillna(df.col1.mean()) 三 . 噪声值 噪声值是指数据中与其他数值相比差异比较大的值,也有的叫离群点等,比如年龄里出来几个150以上的。噪声值会严重干扰模型结果,使结论不真实或偏颇。所以必须要清除这些噪声值,常用的方法:对于单变量的有盖帽法,分箱法,多变量的有聚类法。 盖帽法 我们都学过正态分布,对于均值上下三倍标准差范围外的记录值加一块的概率才为0.01%,故我们可以把这些外围数据替换为各自的均值上下三倍标准差值,即为盖帽法 数据库里可以用case when来替换,python可以写一个函数 def cap(x,quantile=[0.01,0.99]): '''盖帽法处理异常值 Args: x:是series列,连续变量 quantile:上下分位数范围,这里写为0.01和0.99 ''' # 生成分位数,Q01,Q99分别是百分之一分位点和百分之99分位点 Q01,Q99=x.quantile(quantile).values.tolist() # 替换异常值为制定的分位数 if Q01 > x.min(): x = x.copy() x.loc[x < Q01] = Q01 if Q99 < x.max(): x = x.copy() x.loc[x > Q99] = Q99 return(x) 分箱法 分箱法通过考察数据的“近邻”来光滑有序数据的值,有序值分布到一些箱中,通过取各个箱子的特定值如最值,均值,中位数等,这个值就是这个箱子的值,然后置定标准评判这些箱子的值好坏,从而判断各个箱子是好的还是坏的,坏的箱子需要特殊处理。分箱法分为等深分箱:每个分箱样本量一致,等宽分箱:每个分箱取值范围一致。 比如一组数 1 2 66 8 9 2 1 4 6,先排序 1 1 2 2 4 6 8 9 66,再分为三个箱子 箱子A:1 1 2 箱子B:2 4 6 箱子C:8 9 66 我们这里取箱子的平均数,则A为1.3 B为4 C为27.3 很明显这个C值远远大于这组数据的均值和中位数,所以C箱子是坏箱子,则可以集中处理C里的数据 聚类法 前面介绍的都是单变量,多变量的异常值处理需要用到聚类法。 它的思想是正常值都拥有相似的标签,比如前面好的西红柿颜色都是红润的,口感都是酸甜的,表皮都是完整的等等,而坏的西红柿则拥有异于“他人”的特征,比如味道怪异。故我们可以把数据对象分为多个集合,在同一个集合里的对象有较高的相似度,而不同的集合之间的对象差别较大。聚类分析可以通过这些不同的集合挖掘出孤立点,这些孤立点往往就是异常数据。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册