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之编码规范 推荐
May 23 Javascript
Ajax同步与异步传输的示例代码
Nov 21 Javascript
js如何获取object类型里的键值
Feb 18 Javascript
jquery根据属性和index来查找属性值并操作
Jul 25 Javascript
node.js中的fs.fchown方法使用说明
Dec 16 Javascript
JavaScript实现对下拉列表值进行排序的方法
Jul 15 Javascript
改变vue请求过来的数据中的某一项值的方法(详解)
Mar 08 Javascript
微信小程序登录换取token的教程
May 31 Javascript
如何在基于vue-cli的项目自定义打包环境
Nov 10 Javascript
Node.js assert断言原理与用法分析
Jan 04 Javascript
JS实现关闭小广告特效
Jan 29 Javascript
react+antd 递归实现树状目录操作
Nov 02 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读取目录下所有文件的代码
2008/01/07 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
php使用curl模拟多线程实现批处理功能示例
2019/07/25 PHP
零基础学JavaScript最新动画教程+iso光盘下载
2008/01/22 Javascript
nodejs实现获取某宝商品分类
2015/05/28 NodeJs
基于jQuery Circlr插件实现产品图片360度旋转
2015/09/20 Javascript
Nodejs调用WebService的示例代码
2017/09/29 NodeJs
vue页面跳转后返回原页面初始位置方法
2018/02/11 Javascript
详解Vue调用手机相机和相册以及上传
2019/05/05 Javascript
layui字体图标 loading图标静止不旋转的解决方法
2019/09/23 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
ant design vue中表格指定格式渲染方式
2020/10/28 Javascript
[03:39]DOTA2英雄梦之声_第05期_幽鬼
2014/06/23 DOTA
Python使用MD5加密字符串示例
2014/08/22 Python
Python应用03 使用PyQT制作视频播放器实例
2016/12/07 Python
Django 生成登陆验证码代码分享
2017/12/12 Python
Python堆排序原理与实现方法详解
2018/05/11 Python
Python利用公共键如何对字典列表进行排序详解
2018/05/19 Python
python 使用正则表达式按照多个空格分割字符的实例
2018/12/20 Python
如何定义TensorFlow输入节点
2020/01/23 Python
在Django中预防CSRF攻击的操作
2020/03/13 Python
Selenium启动Chrome时配置选项详解
2020/03/18 Python
500行python代码实现飞机大战
2020/04/24 Python
Python如何将函数值赋给变量
2020/04/28 Python
python PIL模块的基本使用
2020/09/29 Python
StubHub巴西:购买和出售您的门票
2016/07/22 全球购物
印度和世界各地的精美产品:Ikka Dukka
2018/02/12 全球购物
门卫岗位安全职责
2013/12/13 职场文书
高中体育教学反思
2014/01/24 职场文书
总账会计岗位职责
2014/03/13 职场文书
诚实守信道德模范事迹材料
2014/08/15 职场文书
社会发展项目建议书
2014/08/25 职场文书
订货会邀请函
2015/01/31 职场文书
人事专员岗位职责
2015/02/03 职场文书
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python
什么是css原子化,有什么用?
2022/04/24 HTML / CSS