数组去重的5种方法
数组去重的5种方法是什么呢?下面就让我们一起来了解一下吧:
数组去重的5种方法分别是使用“Array.from(new Set(arr))”去重;利用for嵌套for,接着使用splice()方法去重;利用indexOf()方法去重;利用includes()方法去重;利用filter()方法去重。
参考范例:
1、使用“Array.from(new Set(arr))”去重。
示例代码为:
var arr = [1,1,8,8,12,12,15,15,16,16];
function unique (arr) {
return Array.from(new Set(arr))
}
console.log(unique(arr))
//[1,8,12,15,16]
2、利用for嵌套for,接着使用splice()方法去重。
示例代码为:
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];
function unlink(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
}
console.log(unlink(arr));
3、利用indexOf()方法去重。
示例代码:
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];
function unlink(arr) {
if (!Array.isArray(arr)) {
console.log('错误!')
return
}
var array = [];
for (var i = 0; i < arr.length; i++) { // 首次遍历数组
if (array.indexOf(arr[i]) === -1) { // 判断索引有没有等于
array.push(arr[i])
}
}
return array
}
console.log(unlink(arr));
4、利用includes()方法去重。
示例代码:
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array =[];
for(var i = 0; i < arr.length; i++) {
if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
array.push(arr[i]);
}
}
return array
}
console.log(unique(arr))
5、利用filter()方法去重。
示例代码:
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];
function unlink(arr) {
return arr.filter(function (item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
console.log(unlink(arr));
以上就是小编的分享了,希望能够帮助到大家。
数组去重的5种方法前端
深入分析数组去重
大家好,我是前端西瓜哥。
数组去重是常见的面试考点,所以我就试着深入学习一下。网上也有很多数组去重的文章,但我自己觉得分析的不够深入,其实其中很多的实现都是重复的,可以归为一类,比如 双重循环法 和 indexOf法 的本质都是双重循环,故写下此文,做进一步的总结,同时加深理解。
1. 双重循环这种方法就很直接,很好理解。那就是创建一个新的空数组,每次我们会从原数组中取出一个元素,拿它和新数组的元素进行一一比较。
如果在新数组没发现和取出元素相等的元素,就将其放入这个新数组中;如果发现有和取出元素相等的元素,不放入新数组中。
当原数组中的数组全都取出来时,这个新数组就是去重后的所有数据了。
这种数组去重的实现的时间复杂度是 O(n^2)。
constunique=arr=>{letres=[];for(leti=0,len=arr.length;i
当然这里的第一个循环可以改为 forEach() 方法,第二个 for 循环可以改为使用 includes() 或者 indexOf() 方法,时间复杂度没什么变化,不过代码更简洁。
constunique=arr=>{letres=[];arr.forEach(item=>{if(!res.includes(item))res.push(item);})returnres;}
2. 查找元素第一次出现的位置
从后往前遍历数组,检测元素第一次出现的位置是否为当前元素的位置。如果不是,说明有重复,移除当前元素;如果没有,就不移除。
之所以从后往前遍历,是因为我们要搬移元素(其实就是 splice)。
当然你也可以选择从前往后遍历,不过这样的话,如果遍历时当前元素被移除了,那么移除元素后的 arr[i] 对应的元素其实是原来 arr[i 1],因此此时 i 不能自增,且结束的条件要改为 i == len-1,就很麻烦。
这种写法不需要创建新的数组,空间复杂度为 O(1)。
constunique=arr=>{for(leti=arr.length-1;i>=0;i--){for(letj=0;j
这里的代码实现是尽量减少时间复杂度的。
说个题外话,其实上面这里还可以再优化一下,因为我们这里的元素搬移并不是一次性搬移到最终的位置上的。优化思路是先标记要所有要删除的元素索引,然后从前往后遍历数组,每遇到第 m 个删除索引,后面的元素就覆盖掉它们往前第 m 位的数组元素,这里就不实现了,也就随便提一下。
如果改为配合使用 filter() 和 includes() 方法的话,我们可以让代码可读性更好一些(性能会稍微下降,因为 incluedes 会遍历整个数组),具体实现就不写了。
3. 排序后去重排序算法有很多种,我们就用 js 自带的排序算法吧。顺带一说,v8引擎 的 sort() 方法在数组长度小于等于10的情况下,会使用插入排序,大于10的情况下会使用快速排序。
排(guai)好(guai)序(zhanhao)后,检查前后两个相邻元素,如果当前元素和前面的元素不相等,才将当前元素放入新数组中。
constunique=arr=>{if(arr.length<2)returnarr;arr.sort();letr=[arr[0]];for(leti=1,len=arr.length;i
这种去重局限性非常大。
它不适用于对象,因为对象不适合进行排序。sort() 的默认排序顺序是根据字符串Unicode码点进行排序,貌似会把对象转为字符串再进行排序,一般的对象都会转为 "[object Object]",无法保证两个引用同一个对象的变量能相邻排列。
4. 使用散列表散列表,在 JavaScript 中是通过对象来实现的。散列表的优点是,一般情况下读取数据的时间复杂度是 O(1)。
但 js 的对象的键只能为字符串类型,不过可以考虑使用 ES6 新增的 Map 数据结构,它允许使用任何类型的值作为键。
下面的实现使用的是普通对象作为散列表,有很大的局限性,无法对 js对象 进行去重(对象都会转为类似 [object Object] 的字符串)。
另外,对于js对象来说,a['1'] 和 a[1] 是相等的,因为1会转换为'1',这样就无法分辨出 1 和 '1',从而错误地在去重过程中丢弃其中的一个元素,所以我做了简单地改良,键名使用的不是 arr[i] 而是 typeof(arr[i]) arr[i]。
constunique=arr=>{letr=[];letmap={};for(leti=0,len=arr.length;i
这种实现方式,时间复杂度可以达到 O(n)。
如果考虑对象也能去重,可以考虑使用 ES6 的 Map。
5. ES6 的 SetES6 提供了新的数据结构。Set 实例会认为两个 NaN 是相等的(尽管 NaN !== NaN),并认为两个对象是不等的(当然这里两个对象的意思,表示的是两个指向不同内存空间的引用类型变量)。
并不太了解 Set 的源码实现,就不分析性能了。
constunique=arr=>{returnArray.from(newSet(arr))}
非常简洁,如果你的运行环境支持 ES6,或者可以编译成 ES5,我很推荐使用这个去重方案。
考虑 NaN 的去重如果要考虑 NaN 的去重,就需要稍微对代码进行一些修改。
简单来说就是,判断 item 是否为 NaN,然后检查返回的数组中是否已有 NaN。如果有,放入数组;否则不放入。
constunique=arr=>{letres=[];lethasNaN=false;arr.forEach(item=>{if(!hasNaN&&Number.isNaN(item)){res.push(item);hasNaN=true}elseif(!res.includes(item)){res.push(item);}})returnres;}
lodash 如何实现去重
简单说下 lodash 的 uniq 方法的源码实现。
这个方法的行为和使用 Set 进行去重的结果一致。
当数组长度大于等于 200 时,会创建 Set 并将 Set 转换为数组来进行去重(Set 不存在情况的实现不做分析)。
当数组长度小于 200 时,会使用类似前面提到的 双重循环 的去重方案,另外还会做 NaN 的去重。
总结一般来说,在开发中,要进行去重的数组并不是很大,不必太考虑性能问题。所以在工程中,为了不把简单的问题复杂化中,建议使用最简洁的 ES6 的 Set 转数组的方案来实现。
当然具体问题具体分析,要根据场景选择真正合适的去重方案。
另外,其实 “相等” 有很多种定义,ES6 中就有四种相等算法,这里就不多说了,有兴趣的话可以看看这篇文章:JavaScript 中的相等性判断。依旧是根据场景选择合适的相等算法。
- 07-21生活
安红我想你是什么梗
- 04-29生活
榴莲开口了放一晚上会坏吗
- 01-23生活
快乐八10个中2个有钱吗
- 04-27生活
糖醋咕噜肉是哪个地方的菜
- 11-25教育
高中新型肺炎作文
- 04-30生活
文字烧和大阪烧的区别是什么
- 06-16生活
防止护膝下滑的小妙招
- 08-05科技
DeX pad是什么
推荐
- 1电脑开机越来越慢怎么办?109
- 2IBM认证怎么报名167
- 3nsdd是什么意思363
- 4如何做好微信营销:提高微信加好友通过率144
- 5冰冻榴莲怎么解冻172
- 6炒薏仁要多久447