之前看知呼中的一个问题,觉得自己需要整理一下: 知呼连接https://www.zhihu.com/question/29558082
先生成array:
var arr = [], num = 0; for (var i = 0; i < 10000; i++) { num = i%4; if(num == 0) { arr.push(Math.floor(Math.random() * 99999)); } else if(num == 1){ arr.push(function(){ var some = Math.random(); }); } else if(num == 2){ arr.push({ a:Math.random() }); } else if(num == 3) { arr.push(`${Math.floor(Math.random() * 99999)}`); } }
第一个方法是 玉伯 的去重方法,利用Object的key唯一的特性进行对比:
function uniq1 (arr){ var hash = {}, ret = []; for(let item of arr) { if(!hash[item]) { hash[item] = true; ret.push(item); } } return ret; }
第二种和第三种是ES6出来以后,利用Set的特性,和数组不同,一个Set不会包含相同元素
function uniq2 (arr) { return Array.from(new Set(arr)) } function uniq3 (arr) { const seen = new Map() return arr.filter((a) => !seen.has(a) && seen.set(a, 1)) }
第四种方法是通过去掉当前的,然后判断是否前面包含相同元素:
function uniq4 (array) { for (var i = array.length; i--;) { var n = array[i] // 先排除 即 如果它是清白的 后面就没有等值元素 array.splice(i, 1, null) if (~array.indexOf(n)) { array.splice(i, 1); //不清白 } else { array.splice(i, 1, n); //清白 } } }
通过跑的时间对比性能:
(function(){ let arrays = []; for(let i = 0; i < 100; i++) { arrays.push(Object.assign([], arr)); } var date = new Date(); for(let i = 0; i < 100; i++) { uniq1(arrays[i]); } console.log('uniq1: ', (new Date() - date)/100.00); var date = new Date(); for(let i = 0; i < 100; i++) { uniq2(arrays[i]); } console.log('uniq2: ', (new Date() - date)/100.00); var date = new Date(); for(let i = 0; i < 100; i++) { uniq3(arrays[i]); } console.log('uniq3: ', (new Date() - date)/100.00); var date = new Date(); for(let i = 0; i < 100; i++) { uniq4(arrays[i]); } console.log('uniq4: ', (new Date() - date)/100.00); })();
跑分结果:
小结:
可以发现前三种方法时间都差不多,用Set的两种稍微快一些。
不过uniq1的去重方法适合各种浏览器的使用,不需要考虑Babel翻译。
而Set是ES6的新功能,需要考虑IE11以下的兼容性问题,但是明显Set
的数据存储结构专门为一种操作作了速度优化, 所以运行速度上面有一些优势。
至于第四种方法,比较前三种明显的时间多出很多,我在运行100遍循环的时候,会感觉明显的卡顿,主要原因还是因为splice方法的时间消耗巨大。好处也显而易见,适合各种浏览器的同时,是在原有array上直接修改,没有创建任何多余的空间。