JavaScript 数组去重常常出如今前端招聘的笔试题里,好比:javascript
有数组 var arr = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0],请用 JavaScript 实现去重函数 unqiue,使得 unique(arr) 返回 ['a', 'b', 'c', '1', 0, 1, '']前端
做为笔试题,考点有二:java
- 正确。别小看这个考点,考虑到 JavaScript 常常要在浏览器上运行,在千姿百态的各类浏览器环境下要保障一个函数的正确性可不是一件简单的事,不信你继续读完这篇博客。
- 性能。虽然大部分状况下JavaScript语言自己(狭义范畴,不包含DOM等延拓)不会致使性能问题,但很不幸这是一道考题,所以面试官们仍是会把性能做为一个考点。
全部的方法都来自网上,学到了才是本身的!!
而后,写在前面,带上咱们可爱的小伙伴。jquery
文章主要是对js数组去重的经常使用方法进行介绍。JS去重,看起来简单,可是其实暗藏许多的小窍门。考的不单单是实现这个功能,更能看出你对计算机程序执行的深刻理解。下面将从数组去重的方法进行详细的了解。es6
两层for循环,for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比。若结果数组中没有该元素,则存到结果数组中。面试
Array.prototype.unique_towFor = Array.prototype.unique_towFor || function(){ var result = []; if(this.length <= 0) return result; result.push(this[0]); for(var i = 1; i < this.length; i++){ var notIn = true; for(var j = 0; j < result.length; j++){ if(this[i] == result[j]){ notIn = false; break; } } if(notIn){ result.push(this[i]); } } return result; }
算法的基本思想,就是,把去重后的结果放在一个临时数组中,对原来数组的元素与临时数组元素比较,临时数组中不存在这个元素的,放入临时数组。算法
Array.prototype.unique_tempArray = Array.prototype.unique_tempArray || function(){ var result = [];//临时数组 for(var i = 0; i < this.length; i++){ if(result.indexOf(this[i]) == -1){ result.push(this[i]); } } return result; }
建立一个新的数组存放结果,和一个空对象。for循环时,每次取出一个元素与对象进行对比,若是这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容做为对象的一个属性,并赋值,存入到对象中。这个方法用做统计也很方便。数组
Array.prototype.unique_objectArray = Array.prototype.unique_objectArray || function(){ var result = []; var obj = {}; for(var i = 0; i < this.length; i++){ if(!obj[this[i]]){ obj[this[i]] = 1; result.push(this[i]); }else{ obj[this[i]] ++; } } return result; }
先把数组排序,而后比较相邻的两个值。 排序的时候用的JS原生的sort方法,JS引擎内部用的是快速排序,此方法速度比较快!无语中。浏览器
Array.prototype.unique_sortArray = Array.prototype.unique_sortArray || function(){ this.sort(); var result = [this[0]]; for(var i = 1; i < this.length; i++){ if(this[i] !== result[result.length - 1] ){ result.push(this[i]); } } return result; }
Array.prototype.unique_es6SetArray = Array.prototype.unique_esSetArray || function(){ return Array.from(new Set(this)); }
Array.prototype.unique_filterArray = Array.prototype.unique_filterArray || function(){ return this.filter(function(item, index, arr){ return arr.indexOf(item) === index; }); }
既然可使用filter的方法,那么也可使用filter加object的方法,这里使用Map对象。性能优化
Array.prototype.unique_es6MapArray = Array.prototype.unique_es6MapArray || function(){ const seen = new Map(); return this.filter(function(item, index, arr){ !seen.has(item) && seen.set(item, 1); }); }
这里的filter函数能够简化,固然也有人这样写
Array.prototype.unique_es6MapArray = Array.prototype.unique_es6MapArray || function(){ const seen = new Map(); return this.filter( (a) => !seen.has(a) && seen.set(a, 1) ); }
最后,可使用第三方库函数jquery和underscore或者lodash
下面以lodash和underscore为例
Array.prototype.unique_3partyArray = Array.prototype.unique_3partyArray || function(){ return _.uniq(arr);//要先引入lodash.js或者underscore.js }
- 以上的全部方法,都来自网上。
- 全部的方法,都必须脚踏实地,在具体应用场景下去分析、去选择,咱们应该按照具体的状况,来选择方法。
- 由于浏览器的多样性,前端的应用场景常常很复杂,性能优化充满挑战,也充满机遇。
- 学会了才是本身的,知道会用会写,才是咱们最终的目标。
方法中,建议参考underscore.js的源代码的方法。如下是underscore.js中uniq的源码。
// Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. // Aliased as `unique`. _.uniq = _.unique = function(array, isSorted, iteratee, context) { if (!_.isBoolean(isSorted)) { context = iteratee; iteratee = isSorted; isSorted = false; } if (iteratee != null) iteratee = cb(iteratee, context); var result = []; var seen = []; for (var i = 0, length = getLength(array); i < length; i++) { var value = array[i], computed = iteratee ? iteratee(value, i, array) : value; if (isSorted) { if (!i || seen !== computed) result.push(value); seen = computed; } else if (iteratee) { if (!_.contains(seen, computed)) { seen.push(computed); result.push(value); } } else if (!_.contains(result, value)) { result.push(value); } } return result; };
文档说明以下:
uniq_.uniq(array, [isSorted], [iteratee]) Alias: unique
Produces a duplicate-free version of the array, using === to test object equality. In particular only the first occurence of each value is kept. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iteratee function.
_.uniq([1, 2, 1, 4, 1, 3]);
=> [1, 2, 4, 3]
本文仅只用于学习、研究和交流目的,我也是学习事后慢慢总结过来的,若是有什么错误或者好的建议,欢迎你们批评指正!