详解javascript数组去重问题

作者:拾光

时间:2026-10-29

浏览:583

本文深入探讨JavaScript中数组去重的多种实现方案。从最基础的嵌套循环对比,到利用ES5的indexOf方法简化代码,再到以空间换时间的高性能对象存储法,以及利用排序和逆向遍历的技巧。文章详细解析了六种经典算法的代码逻辑、优缺点及适用场景,帮助开发者根据实际需求选择最优解。

文章目录

基础嵌套循环法(代码A)

最初构思是创建一个新的结果数组以保存原始数组中的唯一值。通过遍历原始数组并与结果数组内的元素逐一比对来识别重复项。据此编写了代码A:


Array.prototype.clearRepetitionA = function(){
   var result = [];
   var isRepetition;
   for(var i=0; i<this.length; i++){
     isRepetition = false;
     for(var j=0; j<result.length; j++){
       if(this[i] === result[j]){
         isRepetition = true;
         break;
       }
     }
     if(!isRepetition){
       result.push(this[i]);
     }
   }
   return result;
 } 

利用indexOf简化逻辑(代码B)

随后联想到ECMAScript 5标准下的indexOf方法,该功能用于查找数组元素。利用此方法取代了原有的嵌套循环结构,实现了代码B:


Array.prototype.clearRepetitionB = function(){
   var result = [];
   for(var i=0; i<this.length; i++){
     if(result.indexOf(this[i]) == -1){
       result.push(this[i]);
     }
   }
   return result;
 } 

索引对比法(代码C)

代码行数由17行缩减至9行,显著提升了简洁度。鉴于数学问题通常存在多种解法,继续探索其他思路。indexOf方法用于定位数组中首个匹配元素的索引,若无匹配则返回-1;其接受两个参数,第一个为待搜索值,第二个为可选的起始索引,省略时默认从头开始。基于此,考虑到此前方法均侧重于值重复检测,现可通过比较元素首次出现的索引与当前索引是否一致来判定重复。据此编写了代码C:


 Array.prototype.clearRepetitionC = function(){
   var result = [this[0]];
   for(var i=1; i<this.length; i++){
     if(this.indexOf(this[i]) == i){
       result.push(this[i]);
     }
   }
   return result;
 } 

以空间换时间的高效对象法(代码D)

对此方案进行反思后,认为上述三种方法均较为基础,未能想出更多变体。经查阅参考答案以验证思路,发现自身在简单问题上仍具创新潜力。此处省略个人推导过程,直接呈现经典答案及其解析。 首先介绍一种利用空间换时间策略的算法,暂命名为代码D:


Array.prototype.clearRepetitionD = function(){
   var result = [];
   var obj = {};
   var key,type;
   for(var i=0; i<this.length; i++){
     key = this[i];
     type = typeof key;
     if(!obj[key]){
       obj[key] = [type];
       result.push(key);
     }else if(obj[key].indexOf(type)){
       obj[key].push(type);
       result.push(key);
     }
   }
   return result;
 } 

该方案在遍历原始数组时,利用对象obj的属性记录元素值,属性值则为包含类型信息的数组。这种机制能够区分数字1与字符串'1'。通过构建额外对象,有效降低了indexOf方法带来的时间开销,属于较为高效的实现。 若仅满足于上述空间换时间的方案而停止阅读,则错失精华。接下来展示代码E:


 Array.prototype.clearRepetitionE = function(){
   var result = [];
   for(var i=0; i<this.length; i++){
     for(var j=i+1; j<this.length; j++){
       if(this[i] === this[j]){
         j = ++i;
       }
     }
     result.push(this[i]);
   }
   return result;
 }

逆向遍历去重法(代码E)

代码D的空间换时间策略效果有限。代码E看似存在逻辑错误,实则具备去重功能。起初难以理解,经解析后复现才恍然大悟。解析如下:外层循环正向遍历数组,内层循环检查当前元素是否与后续元素重复。若发现后续存在重复元素,则跳过当前元素;若后续所有元素均不重复,则将该元素加入结果数组。此策略旨在获取无重复的最右侧值并加入结果集,相比第一种方法优化了内层循环效率,但结果数组的元素顺序与原始数组不一致。

排序后去重法(代码F)

在欣赏代码E解析后,是否已对其表示赞赏?(此荣誉应归于该方法的创作者)。最后介绍一种先排序后去重的方法,命名为代码F:


Array.prototype.clearRepetitionF = 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;
 } 

该方法首先调用数组的sort方法进行排序,随后执行去重操作。

以上为对javascript数组去重问题的逐步研究过程,通过持续改进代码,共展示了六段代码,期望读者能深入研习并获益。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章