数组去重就是将一个数组中的相同的元素删除,只保留其中的一个。这里的相同,其实是一个陷阱,有好多同学认为值相等即为相同,而忽略了类型的判断。
下面介绍13种原生方式实现数组去重,当中涉及ES6,ES5两种标准,has,Map,filter,reduce,call,apply,set,push,from,indexOf,sort等函数,及函数式编程,原型函数,构造函数等概念。
一、对象键值对解法
解法1
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>对象键值对去重,适用于数组或者数组对象</title> </head> <body> 未区分数字和字符串,耗时13ms,超级快。 <script type="text/javascript"> function removeSame(arr) { // 构建一个新数组,存放结果 var newArray = []; //创建一个空对象 var object = {}; // for循环时,每次取出一个元素与对象进行对比 // 如果这个对象不重复,将它存放到结果数中 // 同时把这个元素的内容作为对象的一个属性,并赋值为true,存到对象中 for (var i = 0; i < arr.length; i++) { // 检测object对象中是否包含遍历到的元素值 if (!object[arr[i]]) { // 如果不包含,将存入对象的元素的值推入到结果数组中 newArray.push(arr[i]); // 如果不包含,存入object对象中该属性名的值设置为true object[arr[i]] = true; } } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[11][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5] console.log(removeSame(arr)); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = removeSame(arr); var tEnd = (new Date()).getTime(); console.log('对象键值对去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法2
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>对象键值对去重</title> </head> <body> 有区分数字和字符串,耗时340ms,占用内存大。 <script type="text/javascript"> Array.prototype.removeSame = function() { // 构建一个新数组,存放结果 var newArray = []; //创建一个空对象 var object = {}; // for循环时,每次取出一个元素与对象进行对比 // 如果这个对象不重复,将它存放到结果数中 // 同时把这个元素的内容作为对象的一个属性,并赋值为1,存到对象中 for (var i = 0; i < this.length; i++) { // 检测object对象中是否包含遍历到的元素值 if (!object[typeof(this[i]) + this[i]]) { // 如果不包含,将存入对象的元素的值推入到结果数组中 newArray.push(this[i]); // 如果不包含,存入object对象中该属性名的值设置为1 object[typeof(this[i]) + this[i]] = 1; } } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('对象键值对去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法3
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>对象键值对去重</title> </head> <body> 有区分数字和字符串,耗时1391ms。 <script type="text/javascript"> Array.prototype.removeSame=function() { // 构建一个新数组,存放结果 var newArray = []; //创建一个空对象 var object = {}; this.forEach(function(value) { var type = Object.prototype.toString.call(value).match(/\s(\w+)/)[1].toLowerCase(); if (!((type + '-' + value) in object)) { object[type + '-' + value] = true; newArray.push(value); } }) return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5 ,"1" ,"2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('对象键值对去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
二、ES6解法
解法1
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>ES6之from去重</title> </head> <body> 更简单,更优化,有区分数字和字符串,耗时165ms。 <script type="text/javascript"> function removeSame(arr){ return Array.from(new Set(arr));// return [...new Set(arr)]也可以实现,效率差不多。 } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(removeSame(arr)); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = removeSame(arr); var tEnd = (new Date()).getTime(); console.log('ES6之from去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法2
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>ES6之filter去重</title> </head> <body> 更简单,更优化,有区分数字和字符串,耗时171ms。 <script type="text/javascript"> function removeSame(arr){ const seen=new Map(); return arr.filter((a) => !seen.has(a) && seen.set(a,1)); } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(removeSame(arr)); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = removeSame(arr); var tEnd = (new Date()).getTime(); console.log('ES6之filter去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法3
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>ES6之filter去重</title> </head> <body> 更简单,有区分数字和字符串,耗时22355ms。 <script type="text/javascript"> function removeSame(arr){ return arr.filter((v,i,context) => context.indexOf(v) === i); } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(removeSame(arr)); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = removeSame(arr); var tEnd = (new Date()).getTime(); console.log('ES6之filter去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
三、for,foreach,Array解法
解法1
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>forEach循环去重</title> </head> <body> 有区分数字和字符串,耗时14778ms。 <script type="text/javascript"> function removeSame() { var newArray = []; this.forEach(function(index) { if (newArray.indexOf(index) == -1) { newArray.push(index); } }); return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(removeSame.apply(arr)); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = removeSame.call(arr); var tEnd = (new Date()).getTime(); console.log('forEach循环去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法2
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>排序后for循环去重</title> </head> <body> 有区分数字和字符串,耗时720ms。 <script type="text/javascript"> Array.prototype.removeSame = function() { //原数组先排序 this.sort(); // 构建一个新数组,存放结果 var newArray = []; for (var i = 1; i < this.length; i++) { // 检查原数中的第i个元素与结果中的最后一个元素是否相同 // 因为排序了,所以重复元素会在相邻位置 if (this[i] !== newArray[newArray.length - 1]) { // 如果不同,将元素放到结果数组中 newArray.push(this[i]); } } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13]["1", 1, 2, "2", 3, 32, 34, 4, 5, 56, "a", "b", "c"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('排序后for循环遍历去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法3
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>for循环去重</title> </head> <body> 有区分数字和字符串,耗时14907ms。 <script type="text/javascript"> Array.prototype.removeSame = function() { // 构建一个新数组,存放结果 var newArray = []; // 遍历数组 for (var i = 0; i < this.length; i++) { //如果当前数组的第i值保存到临时数组,那么跳过 var index = this[i]; //如果数组项不在结果数组中,将这个值推到结果数组 if (newArray.indexOf(index) === -1) { newArray.push(index); } } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5 ,"1" ,"2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('for循环去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法4
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>双重for循环去重</title> </head> <body> 未区分数字和字符串,耗时34762ms。 <script type="text/javascript"> Array.prototype.removeSame = function() { // 构建一个新数组,存放结果 var newArray = [this[0]]; // for循环,每次从原数组中取出一个元素 // 用取出的元素循环与结果数组对比 for (var i = 1; i < this.length; i++) { var repeat = false; for (var j = 0; j < newArray.length; j++) { // 原数组取出的元素与结果数组元素相同 if (this[i] == newArray[j]) { repeat = true; break; } } if (!repeat) { // 如果结果数组中没有该元素,则存放到结果数组中 newArray.push(this[i]); } } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[11][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('双重for循环去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法5
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>双重for循环去重</title> </head> <body> 有区分数字和字符串,耗时69240ms。 <script type="text/javascript"> Array.prototype.removeSame = function() { // 构建一个新数组,存放结果 var newArray = []; // 遍历整个数组 for (var i = 0; i < this.length; i++) { // 遍历是否有重复的值 for (var j = i + 1; j < this.length; j++) { // 如果有相同元素,自增i变量,跳出i的循环 if (this[i] === this[j]) { j = ++i; } } //如果没有相同元素,将元素推入结果数组中 newArray.push(this[i]); } return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13]["a", 1, 3, 4, 56, 32, 34, 2 ,"b","c", 5 ,"1", "2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('双重for循环去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
四、ES5解法
解法1
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Array.prototype.reduce去重</title> </head> <body> 有区分数字和字符串,耗时15258ms。 <script type="text/javascript"> Array.prototype.removeSame = function() { return this.reduce(function(newArray, index) { if (newArray.indexOf(index) < 0) { newArray.push(index); } return newArray; }, []); } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('Array.prototype.reduce去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法2
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Array.prototype.filter去重</title> </head> <body> 未区分数字和字符串,耗时801ms <script type="text/javascript"> Array.prototype.removeSame = function() { var newArray = this.sort(); return newArray.filter(function(v,i,context){ return v != context[i+1]; }); } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[11][1, "2", 3, 32, 34, 4, 5, 56, "a", "b", "c"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('Array.prototype.filter去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
解法3
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Array.prototype.filter去重</title> </head> <body> 有区分数字和字符串,耗时68053ms <script type="text/javascript"> Array.prototype.removeSame = function() { var newArray; newArray = this.filter(function(ele,i,arr) { return arr.indexOf(ele) === i; }); return newArray; } //1、用简单数组测试功能 var arr = [1, 2, 3, 4, 'a', 'b', 1, 3, 4, 56, 32, 34, 2, 'b', 'c', 5, '1', `2`]; // 输出:Array[13][1, 2, 3, 4, "a", "b", 56, 32, 34, "c", 5, "1", "2"] console.log(arr.removeSame()); //2、用随机大额数组测试性能 function removeSameTime(arr) { var tStart = (new Date()).getTime(); var re = arr.removeSame(); var tEnd = (new Date()).getTime(); console.log('Array.prototype.filter去重耗时是:' + (tEnd - tStart) + 'ms'); return re; } function testMain() { var arr = []; for (var i = 0; i < 1000000; i++) { //生成随机数组 arr.push(Math.round(Math.random(i) * 10000)); } //调用去重方法,打印函数执行时间 removeSameTime(arr); } testMain(); </script> </body> </html>
来源:https://www.cnblogs.com/camille666/archive/2013/05/27/js_array_remove_sameelement.html