javascript数组去重的六种方法汇总


Posted in Javascript onAugust 16, 2015

面试前端必须准备的一个问题:怎样去掉Javascript的Array的重复项。据我所知,百度、腾讯、盛大等都在面试里出过这个题目。 这个问题看起来简单,但是其实暗藏杀机。 考的不仅仅是实现这个功能,更能看出你对计算机程序执行的深入理解。

    我总共想出了三种算法来实现这个目的:

Array.prototype.unique1 = function()
{
 var n = []; //一个新的临时数组
 for(var i = 0; i < this.length; i++) //遍历当前数组
 {
 //如果当前数组的第i已经保存进了临时数组,那么跳过,
 //否则把当前项push到临时数组里面
 if (n.indexOf(this[i]) == -1) n.push(this[i]);
 }
 return n;
}
Array.prototype.unique2 = function()
{
 var n = {},r=[]; //n为hash表,r为临时数组
 for(var i = 0; i < this.length; i++) //遍历当前数组
 {
 if (!n[this[i]]) //如果hash表中没有当前项
 {
  n[this[i]] = true; //存入hash表
  r.push(this[i]); //把当前数组的当前项push到临时数组里面
 }
 }
 return r;
}
Array.prototype.unique3 = function()
{
 var n = [this[0]]; //结果数组
 for(var i = 1; i < this.length; i++) //从第二项开始遍历
 {
 //如果当前数组的第i项在当前数组中第一次出现的位置不是i,
 //那么表示第i项是重复的,忽略掉。否则存入结果数组
 if (this.indexOf(this[i]) == i) n.push(this[i]);
 }
 return n;
}

    其中第1种和第3种方法都用到了数组的indexOf方法。此方法的目的是寻找存入参数在数组中第一次出现的位置。很显然,js引擎在实现这个方法的时候会遍历数组直到找到目标为止。所以此函数会浪费掉很多时间。 而第2中方法用的是hash表。把已经出现过的通过下标的形式存入一个object内。下标的引用要比用indexOf搜索数组快的多。

    为了判断这三种方法的效率如何,我做了一个测试程序,生成一个10000长度的随机数组成的数组,然后分别用几个方法来测试执行时间。 结果表明第二种方法远远快于其他两种方法。 但是内存占用方面应该第二种方法比较多,因为多了一个hash表。这就是所谓的空间换时间。  就是这个测试页面,你也可以去看看。

根据hpl大牛的思路,我写了第四种方法:

Array.prototype.unique4 = function()
{
 this.sort();
 var re=[this[0]];
 for(var i = 1; i < this.length; i++)
 {
 if( this[i] !== re[re.length-1])
 {
  re.push(this[i]);
 }
 }
 return re;
}

    这个方法的思路是先把数组排序,然后比较相邻的两个值。 排序的时候用的JS原生的sort方法,JS引擎内部应该是用的快速排序吧。 最终测试的结果是此方法运行时间平均是第二种方法的三倍左右,不过比第一种和第三种方法快了不少。

第五种方法

最近在做【搜索历史记录】功能也用到,开始用了 indexOf 方法,该方法在 ECMA5才有支持,对于 IE8- 就不支持了。

我们可以自己写一个函数(Array对象的方法都是定义在原型对象上的),如下:

Array.prototype.unique = function(){
  var length = this.length;
  if(length <= 1){
    return this;
  }
  if(!Array.prototype.indexOf){    
    Array.prototype.indexOf = function(item){
      var l = this.length, i = 0, r = -1;
      if(l <= 0){


 
return -1;



 }
      for(; i < l; i++){
        if(this[i] === item){
          r = i;
        }
      }
      return r;
    }
  }
  
  var result = []; //去重数组
  for(var i = 0; i < length; i++){
    if(result.indexOf(this[i]) === -1){
      result.push(this[i]);
    }
  }
  return result;
}

第六种方法

Array类型并没有提供去重复的方法,如果要把数组的重复元素干掉,那得自己想办法:

function unique(arr) {
  var result = [], isRepeated;
  for (var i = 0, len = arr.length; i < len; i++) {
    isRepeated = false;
    for (var j = 0, len = result.length; j < len; j++) {
      if (arr[i] == result[j]) {  
        isRepeated = true;
        break;
      }
    }
    if (!isRepeated) {
      result.push(arr[i]);
    }
  }
  return result;
}

总体思路是把数组元素逐个搬运到另一个数组,搬运的过程中检查这个元素是否有重复,如果有就直接丢掉。从嵌套循环就可以看出,这种方法效率极低。我们可以 用一个hashtable的结构记录已有的元素,这样就可以避免内层循环。

Javascript 相关文章推荐
JavaScript Base64编码和解码,实现URL参数传递。
Sep 18 Javascript
一个可绑定数据源的jQuery数据表格插件
Jul 17 Javascript
jquery选择器(常用选择器说明)
Sep 28 Javascript
利用JS来控制键盘的上下左右键(示例代码)
Dec 14 Javascript
分享Javascript实用方法二
Dec 13 Javascript
jquery实现具有嵌套功能的选项卡
Feb 12 Javascript
详解JavaScript RegExp对象
Feb 04 Javascript
webpack教程之webpack.config.js配置文件
Jul 05 Javascript
jquery学习笔记之无new构建详解
Dec 07 jQuery
解决vue-router中的query动态传参问题
Mar 20 Javascript
JavaScript实现图片合成下载的示例
Nov 19 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
Feb 08 Javascript
JS+CSS实现下拉列表框美化效果(3款)
Aug 15 #Javascript
js时钟翻牌效果实现代码分享
Jul 31 #Javascript
js实现点击文本框显示日期选择器特效代码分享
May 21 #Javascript
jQuery树形下拉菜单特效代码分享
Aug 15 #Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
Aug 15 #Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
Nov 18 #Javascript
Jquery幻灯片特效代码分享--鼠标点击按钮时切换(1)
Aug 15 #Javascript
You might like
PHP与SQL注入攻击防范小技巧
2011/09/16 PHP
PHP中使用cURL实现Get和Post请求的方法
2013/03/13 PHP
php求两个目录的相对路径示例(php获取相对路径)
2014/03/27 PHP
在SAE上搭建最新wordpress的方法
2014/12/21 PHP
WebQQ最新登陆协议的用法
2014/12/22 PHP
PHP编写学校网站上新生注册登陆程序的实例分享
2016/03/21 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
动态调用css文件——jquery的应用
2007/02/20 Javascript
不错的JS中变量相关的细节分析
2007/08/13 Javascript
javascript自执行函数之伪命名空间封装法
2010/12/25 Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
网站繁简切换的JS遇到页面卡死的解决方法
2014/03/12 Javascript
js遍历子节点子元素附属性及方法
2014/08/19 Javascript
Javascript Memoizer浅析
2014/10/16 Javascript
jQuery和AngularJS的区别浅析
2015/01/29 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
2015/07/18 Javascript
论Bootstrap3和Foundation5网格系统的异同
2016/05/16 Javascript
AngularJS表单和输入验证实例
2016/11/02 Javascript
Javascript仿京东放大镜的效果
2017/03/01 Javascript
搭建简单的nodejs http服务器详解
2017/03/09 NodeJs
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
[01:16]2014DOTA2 TI专访C9战队EE:中国五强中会占三席
2014/07/10 DOTA
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
浅析Python装饰器以及装饰器模式
2018/05/28 Python
python pymysql链接数据库查询结果转为Dataframe实例
2020/06/05 Python
Python使用Selenium实现淘宝抢单的流程分析
2020/06/23 Python
Python collections模块的使用方法
2020/10/09 Python
玩具反斗城天猫官方旗舰店:享誉全球的玩具店
2017/10/10 全球购物
一份关于丢失公司财物的检讨书
2014/09/19 职场文书
校园运动会广播稿
2014/10/06 职场文书
教师廉洁自律个人总结
2015/02/10 职场文书
少先队大队委竞选口号
2015/12/25 职场文书
HR必备:超全面的薪酬待遇管理方案!
2019/07/12 职场文书
python实现简单区块链结构
2021/04/25 Python
MySQL创建表操作命令分享
2022/03/25 MySQL
python数字图像处理数据类型及颜色空间转换
2022/06/28 Python