数组去重三种方法
问题情境
去除数组中重复的元素,输出不重复的元素数组
思路方向
- 将数组中重复的元素删除
- 将数组中不重复的元素取出
- 利用其它 JavaScript 特性和 API 直接去重
这一思路中有些 API 涉及ES6中的某些知识暂不提及
方法一利用数组对数组中的元素进行比较取出不重复元素去重
原理
创建一个新数组存放元素,遍历原数组中的元素,如果原数组中的某个元素没有与新数组中的元素重复就把该元素放进新数组中
流程
- 先定义一个新的数组,用来存储不重复的元素
- 利用循环将原数组中的每个元素,逐个取出与新数组中的元素进行比较
- 如果有相等的值则结束循环,如果循环结束后新数组的长度与新数组的循环变量相等,那么说明新数组中没有雨原数组重复的元素,此时,元素组中的元素添加进新数组中
- 最后返回新数组
function unique(arr) {
var result = [];
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < result.length; j++) {
//此时说明遍历新数组中元素后,新数组中有与原数组中重复的元素,跳出循环
if (result[j] == arr[i]) {
break;
}
}
if (result.length == j) {
//此时说明遍历新数组中所有元素后,新数组中没有与原数组中重复的元素,把该元素放进新数组中
result[j] = arr[i];
}
}
return result;
}
注意
- 该方法是通过循环对数组进行遍历,效率较低,如果数据过多会占用较多的内存。如果对效率要求较高,不推荐使用
- 该方法逻辑简单,容易理解,推荐初学者尝试
方法二利用对象的重名属性被覆盖进行去重
原理
创建一个对象存放数据,遍历原数组中的所有元素,每查找一个元素,就把该元素作为属性名放进创建的对象中
根据对象的特点,如果属性名有重复的会被后面的属性名覆盖,最终只会有一个该属性名
流程
- 先创建一个对象,用来存储数组中的元素作为属性名
- 遍历数组中的每一项,把每一项作为对象的属性名
- 遍历对象,将对象中的属性名作为元素存入数组中
function unique(arr) {
var obj = {};
for (var i = 0; i < arr.length; i++) {
//遍历数组,将数组中的每一项作为属性名放进对象中,如果有重名属性名,会自动覆盖
obj[arr[i]] = i;
}
var result = [];
for (var key in obj) {
//取出对象中的属性名作为元素存入数组中,对象的属性名为 string 类型需要将其转换成 number 类型
result.push(Number(key));
}
return result;
}
注意
- 该方法由于是利用对象将数组元素作为属性名存入,所以去重后的元素为 string 类型,如果后续还会对排序后的数组进行操作,需要将元素转换成 number 类型
- 该方法中对象的属性值可以任意赋值,最终返回结果只取出属性名
方法三利用数组API删除重复元素去重
原理
利用数组中的splice()方法将重复的元素删除
流程
- 循环遍历数组,遍历都从数组的头部开始,将元素与后面的每一个元素比较
- 如果有重复的元素,将该位置的元素删除,并将循环变量减一
function unique(arr) {
//从数组的第一个元素开始遍历
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--;
}
}
}
return arr;
}
注意
- 该方法会对原数组进行修改,如果不想在原数组中进行操作不推荐使用
- 该方法中的第二层循环中的循环变量减一,是因为splice()删除数组中的元素后,数组元素的下标会减一,相当于元素向前移了一位,因此为了不遗漏元素,需要减一
- 该方法通过循环对数组进行遍历,效率较低,如果数组元素太多会影响速度
总结
- 方法一利用新数组与原数组重元素对比去重是将不重复的元素取出存入新数组中达到去重的效果
- 方法二利用对象将元素作为对象的属性名去重是将重复的覆盖(相当于合并)达到去重的效果
- 方法三利用 splice() 方法去重是将重复的元素删除达到去重的效果
以上只是自己在使用中总结的方法,尚不是全部的方法,如果不能满足,还请见谅。