废话很少说,直接拿干货!javascript
先说说这个实例的要求:写一个方法实现数组的去重。(要求:执行方法,传递一个数组,返回去重后的新数组,原数组不变,实现过程当中只能用一层循环,双层嵌套循环也可写,只作参考);java
先给初学者解释一下什么叫数组去重(老鸟跳过):意思就是讲数组里面重复的元素去掉,好比说var arr = [3,2,4,2,1,2]; 数组去重获得的新数组是 [3,2,4,1],就是这么一个功能。数组
实现方法比较简单,实现的方式也比较多,不少大牛也写过相关的文章,之因此写这边博客,旨在一是备忘,二是给初学者能更好的理解其实现的原理,好,咱们看第一种实现方式:性能
第一种,经过遍历新数组来去重学习
var arr = [1,'b','b',4,3,3,4,5,1]; //第一种 Array.prototype.unique1 = function(){ var arr1 = []; //定义一个新数组 for(var i=0;i<this.length;i++){ if(arr1.indexOf(this[i]) == -1){//判断目标数组中在原数组里是否存在 arr1.push(this[i]); } } return arr1; } console.log(arr); //[1,'b','b',4,3,3,4,5,1] console.log(arr.unique1()); //[1, "b", 4, 3, 5] //这种方法的主要思路就是,新建一个数组,而后在原数组中,从第一个开始,看看新数组里面有没有这个元素,若是有,就忽略,而后进行下一个,若是没有,则把这个元素存到新数组里面, //也就是说,每一次比较,都会遍历新数组,直到找到相同元素为止,比较耗性能
若是你们不习惯这个写法,能够改为下面的写法,效果是同样的:this
var arr = [1,'b','b',4,3,3,4,5,1];
function unique1(arr){ var arr1 = []; for(var i=0;i<arr.length;i++){ if(arr1.indexOf(arr[i]) == -1){//判断目标数组中在原数组里是否存在 arr1.push(arr[i]); } } return arr1; } console.log(arr); //[1,'b','b',4,3,3,4,5,1] console.log(unique1(arr)); //[1, "b", 4, 3, 5]
下面的方法我就不改写法了,大家能够按照上面的格式来改写一下,结果我也不输出了,由于结果是同样的,注释写在代码中,慢慢体会一下prototype
第二种,经过hash表(这个概念有点大,具体原理就不在这里细说了,有时间我会单独写一遍,这是好东西)实现对象
var arr = [1,'b','b',4,3,3,4,5,1];
Array.prototype.unique2 = function(){ var hash = {}; //定义一个hash表 var arr1 = []; //定义一个新数组 for(var i=0;i<this.length;i++){ /* 这里比较难理解,咱们一步一步来看: hash是一个对象,则存在键值对(key:value),只不过如今是为空的,因此hash[key] = value; 第一步:i=0;this[i]=this[0]=1; hash[this[0]] = hash[1] , 由于hash初始为空,没有找到key=1的值,因此而后undefined, 执行下一步:hash[1] = true(此时hash对象就有了第一组键值对),将原数组的第一个数添加到新数组中,重复第一步 由于不重复的判断hash的值都是undefined,而重复的都为true了,因此不重复都被添加到新数组中 由于hash表存的值是存的地址,放在堆内存中,因此有多少个不重复的元素,就要分多少个内存来存放,因此这种方法比较占内存,可是相比之下,这种的运算运动是最快的, 这也就是用空间来换取时间了,数据量比较小,推荐用此方法 */ if(! hash[this[i]]){ hash[this[i]] = true; arr1.push(this[i]); } } return arr1; } console.log(arr); console.log(arr.unique2());
第三种,经过遍历自身的位置是否一致来实现blog
var arr = [1,'b','b',4,3,3,4,5,1];
Array.prototype.unique3 = function(){ var arr1 = []; //定义一个新数组 for(var i=0;i<this.length;i++){ if(this.indexOf(this[i])==i){ //这里也是indexOf遍历,看从第一个元素在原数组中的位置,若是第一次出现的位置和下标相等,说明当前元素的不重复的,若是不等,说明该元素前面已经出现过 arr1.push(this[i]); } } return arr1; } console.log(arr); console.log(arr.unique3());
第四种,这个有点意思,只能运用到特殊场合,就是先跟数组排序,而后22比较,输出一个排序过的新数组排序
Array.prototype.unique4 = function(){ /* 这里是思路是,先排序(默认从小到大),而后将原数组的第一个给新数组, 由于是通过排序的,因此重复的只会存在在相邻位置 这里就至关因而作22比较,若是相等,则进行下一组,若是不相等,则把这个数存到新数组中,用这个数再进行比较 */ this.sort(); var arr1 = [this[0]]; for(var i=1;i<this.length;i++){ if(this[i] !== arr1[arr1.length-1]){ arr1.push(this[i]); } } return arr1; } console.log(arr); console.log(arr.unique4());
哇哈,打完收工!
要求里面还说,可使用双层嵌套循环来实现,没法就是用2层for循环,让每个与原数组去比较
Array.prototype.unique5 = function(){ //双层循环,一一比较 for(var i=0;i<this.length;i++){ //从0开始 for(j= i+1;j<this.length;j++){ //从1开始,逐个比较 if(this[i] === this[j]){ //若是恒定 this.splice(j,1); //就将这个元素删掉 } } } return this; } console.log(arr); console.log(arr.unique5());
这种写法的循环次数太多,不推荐,有人会说,第一种和第三种不也是每次都遍历一遍吗?跟第5种感受也差很少呢?是的,你能这么理解,说明你理解了,可是呢,又不是特别的理解,咱们说差很少那可就差太多了,indexOf()表示的是找到第一个匹配的元素就会
中止遍历,而第5种则是无论找不找获得,都会把整个数组遍历一遍,若是数据量大,那你以为哪一个性能要好一点?
特别注意的一点:若是在比较两两之间的值是全等或不等的时候,必定要用恒定(===)和不恒定(!==),由于这会涉及到元素的类型上,如 1与'1'是不恒等的!
上面的可真是干货了,一点水分都没有,只能靠你们本身领悟了!
行文仓促,在下才疏学浅,若是你们有更好的实现方法,请你贴出来学习一下,那就不胜感激了,若是有不对的地方,万望指正,谢谢!