JavaScript数字数组去重的四种方法及性能对比
本文深入探讨了在 JavaScript 中去除数组重复项的多种实现方式,重点分析了基于双层循环、排序替换、对象属性映射以及排序相邻比较这四种核心算法,并通过具体的性能测试脚本对比了它们的执行效率。
结果与目标
在数据处理过程中,经常需要去除数组中的重复元素。不同的实现思路在代码复杂度和运行性能上存在显著差异。本文将展示如何通过 Array.prototype 扩展原生方法来实现去重,并直观呈现它们在处理包含大量随机数据的数组时的耗时表现。
准备条件
所有示例均基于浏览器环境运行。为了准确评估不同方法的性能,我们需要一个模拟的大规模随机数据源,以及一个能够记录代码执行时间的监控工具。以下是用于生成测试数据和统计耗时的基础结构。
第1步:构建测试数据源
为了观察去重效果及性能,我们首先生成一个包含2000个随机数字(范围1-2000)的字符串数组。这段代码通过闭包维持状态,确保每次调用 test() 都能返回一份新鲜的数据副本,以保证测试的准确性。
var test=(function() {
var arr2=[];
for(var i=0; i<2000; i++) {
var t=i;
t=parseInt(Math.random()*2000)+1;
arr2[i]=(t.toString());
}
return function(){
return arr2;
};
})();
第2步:集成性能监控工具
使用自定义的 Watch 对象来标记代码段的开始与结束,自动计算耗时并生成可视化报告。该工具会在页面底部以条形图形式展示各方法的耗时占比,便于直观对比。
var Watch = {
result: [],
guid: -1,
totalTime: 0,
start: function(title){
this.result[++this.guid] = [title || this.guid, new Date().getTime()];
},
stop: function(){
var r = this.result[this.guid];
var t = new Date().getTime() - r[1];
this.totalTime += t;
r[1] = t;
},
report: function(parent){
// ... 省略部分DOM操作代码 ...
parent.appendChild(div);
div = null;
this.totalTime = 0;
this.guid = -1;
this.result=[];
}
};
// 简易控制台兼容处理
if(!console){
var console={};
console.log=function(str){alert(str);}
}
真实操作顺序
以下是四种核心的去重算法实现及其逻辑解析。
第3步:使用双层循环遍历去重 (unique1)
目的: 最直观的去重逻辑,适合理解基础算法原理。
入口: 数组原型。
动作: 创建新数组 r。外层循环遍历原数组,内层循环检查新数组中是否已存在当前元素。若不存在,则加入新数组;若存在,则跳过(continue label)。
Array.prototype.unique1 = function () {
var r = new Array();
label:for(var i = 0, n = this.length; i < n; i++) {
for(var x = 0, y = r.length; x < y; x++) {
if(r[x] == this[i]) {
continue label;
}
}
r[r.length] = this[i];
}
return r;
}
第4步:利用排序与正则表达式去重 (unique2)
目的: 利用字符串处理能力简化代码,但需注意类型转换风险。
入口: 数组原型。
动作: 先将数组排序,转为字符串后,使用复杂的正则表达式匹配重复出现的子串并将其替换。最后再拆分回数组。这种方法在处理纯数字字符串时有效,但对对象或特殊格式可能失效。
Array.prototype.unique2 = function () {
return this.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
}
第5步:利用对象属性唯一性去重 (unique3)
目的: 在数据量较大时提供较优的性能表现。
入口: 数组原型。
动作: 创建一个临时对象 temp。遍历原数组,将每个元素作为对象的键值存入。由于对象键名不可重复,重复的元素会被后面的覆盖或忽略。最后遍历对象获取所有键名组成新数组。注释中提到此法在数组很大时最快。
Array.prototype.unique3 = function() {
var temp = {}, len = this.length;
for(var i=0; i < len; i++) {
var tmp = this[i];
if(!temp.hasOwnProperty(tmp)) {
temp[this[i]] = "my god";
}
}
len = 0;
var tempArr=[];
for(var i in temp) {
tempArr[len++] = i;
}
return tempArr;
}
第6步:排序后相邻比较去重 (unique4)
目的: 避免内层循环,通过排序使重复项相邻从而线性扫描。
入口: 数组原型。
动作: 先对原数组进行排序。随后遍历数组,如果当前元素与下一个元素相同,则跳过;否则将其加入结果数组。注意此方法会改变原数组的顺序。
Array.prototype.unique4 = function () {
var temp = new Array();
this.sort();
for(i = 0; i < this.length; i++) {
if( this[i] == this[i+1]) {
continue;
}
temp[temp.length]=this[i];
}
return temp;
}
完成判断与性能测试
在页面加载完成后,依次调用上述四种方法,并通过 Watch 工具输出耗时对比。测试结果显示了每种方法处理2000条数据的实际执行时间,其中 unique3 通常在大数据量下表现最佳。
简要总结
以上关于 JavaScript 数字数组去重四种实现方式及性能测试的详细内容,更多关于 JavaScript 数组优化的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













