数组去重就是将一个数组中的相同的元素删除,只保留其中的一个。这里的相同,其实是一个陷阱,有好多同学认为值相等即为相同,而忽略了类型的判断。
下面介绍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