在学习数组的时候,我们总是能遇到给数组去掉其中相同的值的问题今天来写一写数组的几种去重方法。
不用api去重
首先我们分析一下这个题的思路,我们既然想要给数组去重,让重复的值只出现一次,那么我们首先就得定义一个空数组去存放不重复的值,定义完了。我们得去循环原数组的值,取出原数组的值。取出了原数组的值干嘛呢。肯定是要和新数组的每个值去比较,如果发现原数组的值在新数组中有相同的,就不加进去,如果没有相同的,就加到新数组里面去。基本思路分析完了,就来看下代码。
function noApi1(){
var arr = ['a','a','a','b','b','c','c','d'];
var arr_son = [];
//第一个循环,遍历arr
for(var i = 0; i < arr.length; i++){
//第二个循环,遍历arr_son
for(var j = 0; j < arr_son.length; j++){
//判断原数组在新数组中有没有相同的值
if(arr_son[j] == arr[i]){
break;//如果有就退出本次循环
}
}
//如果没有就加进新数组
if(j == arr_son.length){
arr_son[arr_son.length] = arr[i];
}
}
console.log(arr_son);
}
从代码上来看,没有什么难理解的,唯一一个稍微有点需要思考的就是里面那个循环下面的判断,其实也很好理解,为什么没有写在里面那个循环里面,因为我们是先从外面一个循环拿出当前在arr这个数组的一个数,去和arr_son作比较,这个比较肯定得去吧arr_son里面的值都给比完才能看到是不是有形同的,如何确保完全比完了而不是中途比到了相同的退出循环的呢,完全比完了就是在俩面那个循环j == arr_son.length的时候是完全比完退出循环的,如果比较的时候有相同的肯定会进去里面的那个if判断,进去if之后就会执行break;跳出循环,那么j != arr_son.length,就不会进入外面的判断,也就不会往新数组里面加值。代码到这儿就完了,很简单。看看下一种方法
关联数组去重
此方法依然不用api,需要有一个关联数组的概念,关联数组就是自定义数组下标的数组,就是我们不用0123作为数组下标,自己定义一个下标,可以是一个字符,可以是一个字符串等等,那么了解了这个关联数组,我们再来分析一下这道题,首先我们需要定义两个空的数组,其中一个作为关联数组,然后我们创建一个循环,循环遍历arr;在循环里面去判断,判断的内容就是以当前遍历到的值作为关联数组的下标,判断在这个下标上存不存在值,如果不存在,就可以进行把当前下标的值赋给新数组。思路这样分析,我们看看代码。
function relationArr(){
var arr = ['a','a','a','b','b','c','c','d'];
for(var i = 0, arr_son = [], hash = []; i < arr.length; i++){
if(hash[arr[i]] == undefined){
hash[arr[i]] = true;
arr_son[arr_son.length] = arr[i];
}
}
console.log(arr_son);
}
看了代码我们在分析一下,首先我定义了两个数组,把arr_son作为存放无重数据的新数组,把hash作为关联数组,然后进入循环里面的判断,循环里面的判断就是判断在当前遍历到的值为下标下在hash中有没有值,若没有就是返回undefined,那么等式成立就进入循环,进入循环之后及时把以当前下标的hash数组中的值值为true(赋啥值都行,保证等式左边有值就行)。那么当在arr中遍历到同样的值来作为hash的下标在hash数组中就存在值,就不会再次通过判断,也就不会重新赋值。
使用api去重
使用splice方法
splice方法可以在修改原数组的情况下去给数组删除,修改,添加。首先还是要分析一下这个题。这个题还是要进行嵌套循环,第一个循环取出一个值,第一个循环取出之前的那个值后面的值,去判断,有重复的,就去掉后面取出来的值,就行了。基本思路出来了,就再来看代码。
function spliceArr(){
var arr = ['a','a','a','b','b','c','c','d'];
for(var i = 0; i < arr.length; i++){
for(var j = i + 1; j < arr.length; j++){
if(arr[i] == arr[j]){
arr.splice(j, 1);
j--;
}
}
}
console.log(arr);
}
可以看到里面的循环是从i+1开始的,这是确保总是在前面一个循环遍历到的值后面在去遍历。因为前面和本身已经不用遍历了。然后在进入里面的判断就是判断当前遍历到的值在后面有没有出现,如果在后面有出现,就进入循环,去删除后面的值。然后执行完了删除,下面还加了一个j–;这个是为了确保在删除值之后,原数组就被改变了,那么里面的数据将会变化,我们细细的分析这个j–;假如我们大的遍历当前遍历到了第一个a,那么里面的循环将遍历第二个a,此时出现重复,就会被删除,新的数组将会是 [‘a’,‘a’,‘b’,‘b’,‘c’,‘c’,‘d’];当我们删除了这一个值,并不会跳出这个循环。所以继续执行里面的循环,继续执行里面的循环的情况下,此时是第二次循环,那么 j 此时就是2,但是因为原数组改变了此时的下标为2的地方是‘b’,不是修改之前的‘a’,就相当于第三个‘a’没有被遍历到,此时 j-- 就是为了让往前进一位的‘a’能被遍历到。
利用indexOf和push去重
indexOf是返回找到的值的下标,但是没找到的话就会返回-1,那么这个题首先还是要循环一遍,遍历数组,当从数组里面拿到一个值之后,定义一个新数组,用新数组的indexOf方法去在新数组里面找当前遍历到的值在新数组中存不存在,存在就不执行什么,继续下一次遍历,不存在就把当前的值加到新数组中去,分析完了看代码。
function ifArr(){
var arr = ['a','a','a','b','b','c','c','d'];
for(var i = 0, arr_son = []; i < arr.length; i++){
if(arr_son.indexOf(arr[i]) == -1){
arr_son.push(arr[i]);
}
}
console.log(arr_son);
}
进入循环过后,就判断。如果在arr_son里面没有找到当前值,返回的是-1,等式成立,进入循环。赋值push方法是在数组最后添加一个值,也可也使用unshift()方法;如果在arr_son里面找到了值,返回的就是下标,所以等式不成立,就不会重新添加值。
在原型链上去重
在js中,每个方法都默认会有一个原型,我们要做的就是在数组在的原型上定义一个方法去重,由于对原型链暂时理解不深,所以本例不做过多解释。
Array.prototype.delArr = function(){
for(var i = 0, arr_son = [], hash = []; i < this.length; i++){
if(hash[this[i]] == undefined){
hash[this[i]] = true;
arr_son.push(this[i]);
}
}
return arr_son;
}