数组去重
数组去重一直是我们老生常谈的东西了,但是真正的让我们对某个数组去重,我们是不是能毫无畏惧呢,哈哈哈。来让我们一起来看看这个东西,达成一个新的成就点吧。😉
什么是数组去重
俗话说,知己知彼,我们才能百战百胜。我们在对一个数组进行去重之前我们要知道数组去重到底是什么。
好,那现在就来好(hu)好(bian)说(luan)下(zao)啊,这个数组去重啊,其实就是。。。😜
数组去重。
好了,正经起来。其实数组去重,就是将一列数组进行去重,顾名思义,数组中可能有很多重复的元素,我们将这些重复的元素删去,这个过程就是数组去重。
数组去重的方法
我反复查看了好多大佬的博客,他们写了好多好多种方法,看起来牛X轰轰的,但是我仔细一看,其实这就是两种法子,暴力和非暴力嘛。哎,我自己总结一下吧,心累累。😓
暴力解法
暴力解法1(splice
删除法)
别看是暴力方法,其实这个是我们最为常用的方法呢🙄
思路
进行两层循环遍历,将每一个元素进行两两对比,发现有相同的就删除元素。
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
console.log(arr.valueOf());//[1,'true', false,undefined, NaN, NaN,'NaN','a',{},{}]
特点
- 两次循环导致,时间复杂度为O(N^2)
- 使用有局限性,无法对特别的元素进行去重,比如
NaN
无法去重,null
则直接消失,对象也无法去重。
暴力解法2(无脑排序法)
这个方法是我一直都使用的方法,所以写在这,手动捂脸。
思路
结合额外的栈,进行排序之后一层循环比较前后两个元素是否相等,然后进行去重。
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
arr.sort();
var array = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] != arr[i - 1]) {
array.push(arr[i])
}
}
console.log(array.valueOf())//[1,'true', false,undefined, NaN, NaN,'NaN','a',{},{}]
特点
其实就和上面的差不多,也是无法对那些特别的(无法进行数值比较的)元素进行去重。
暴力解法3(indexOf
)
思路
结合栈,无需排序即可达到去重的目的。indexOf()
方法来判断是否存在元素相同
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
var array = [];
for (let i = 0; i < arr.length; i++) {
//判断我们遍历到的元素是否存在于我们使用的栈数组中
if (array.indexOf(arr[i]) === -1) {
array.push(arr[i]);
}
}
console.log(array.valueOf())
特点
- 这个方法无法对特别的元素进行去重
- 增加了空间复杂度
暴力解法4(includes
)
思路
结合栈,无需排序即可达到去重的目的。includes()
方法来判断是否存在元素相同
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
var array = [];
for (let i = 0; i < arr.length; i++) {
//判断我们遍历到的元素是否存在于我们使用的栈数组中
if (array.indexOf(arr[i]) === -1) {
array.push(arr[i]);
}
}
console.log(array.valueOf())
特点
使用了数组的includes
方法,换汤不换药思路与上面的基本相同
暴力解法5(数组的处理函数)
数组有几个方法,可以让我们更方便的对数组进行操作。
filter
,reduce
,map
等
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item) === index;
});
}
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr))
function unique(arr) {
return arr.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);
}
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr));
特点
不想说了,和前面都是一样的,没啥说的。
暴力解法6(递归法)
PS:我觉得这种办法时间复杂度很高啊,不知道为什么有的博主把这个放在这里将,感觉没啥用,还不如前面的哈哈哈。
function unique(arr) {
var array = arr;
var len = array.length;
array.sort(function(a, b) { //排序后更加方便去重
return a - b;
})
function loop(index) {
if (index >= 1) {
if (array[index] === array[index - 1]) {
array.splice(index, 1);
}
loop(index - 1); //递归loop,然后数组去重
}
}
loop(len - 1);
return array;
}
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr))
各位看官康康就行,嘻嘻嘻
投机取巧法
Set数据类型
我们都知道Set
数据类型有一个特点,就是其中的数据是不重复的,我们正好可以利用这一特点,让我们的数组去重变得简单。
ES6
数组拓展符(…)
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log([...new Set(arr)]);
特点
- 利用了Set数据类型的特点,达到去重的目的
- 这种方法依旧无法对空对象进行去重
Map数据类型
思路
哈希表的特点就是存储的每一个元素都有键值对,那么我们遍历数组的时候给每一个元素都进行标记,那么下次访问到新的元素的时候只需要判断一下是否访问过即可。
function unique(arr) {
let map = new Map();
let array = new Array(); // 数组用于返回结果
for (let i = 0; i < arr.length; i++) {
if (map.has(arr[i])) { // 如果有该key值
map.set(arr[i], true);
} else {
map.set(arr[i], false); // 如果没有该key值
array.push(arr[i]);
}
}
return array;
}
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
console.log(unique(arr))
特点
- 无法对空对象进行去重
对象利用法
唉看这个名字就知道这个方法很不好,利用对象,唉,罪过。言归正传~
此对象非彼对象,我们都知道对象的属性是不可以重复的,啊,灵光一闪。那么我们就可以利用这个特点,将数组去重,机智的’‘小天才’’。
思路
先创建一个新对象,然后使用数组的方法,进行遍历选择,如果在对象中没有属性的话,我们就将其设置为true,否则就是false.
返回即可去重,利用的就是对象的属性的唯一性。
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];
function unique(arr) {
var obj = {};
return arr.filter((item, index, arr) => {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
console.log(unique(arr));
特点
个人感觉这是目前最完美的数组去重方法了,它可以将所有的元素一一去重。建议大家多多使用。(๑•̀ㅂ•́)و✧