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更改class和id的方法
Oct 10 Javascript
jquery中插件实现自动添加用户的具体代码
Nov 15 Javascript
JQuery中上下文选择器实现方法
May 18 Javascript
jQuery插件实现文件上传功能(支持拖拽)
Aug 27 Javascript
javascript实现滚动效果的数字时钟实例
Jul 21 Javascript
HTML5 canvas 9绘制图片实例详解
Sep 06 Javascript
JS实现超简单的汉字转拼音功能示例
Dec 22 Javascript
js实现简单的计算器功能
Jan 16 Javascript
vue绑定设置属性的多种方式(5)
Aug 16 Javascript
JavaScript判断日期时间差的实例代码
Mar 01 Javascript
js防抖和节流的深入讲解
Dec 06 Javascript
node.js通过Sequelize 连接MySQL的方法
Dec 28 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
阿拉伯的咖啡与水烟
2021/03/03 咖啡文化
不用mod_rewrite直接用php实现伪静态化页面代码
2008/10/04 PHP
ThinkPHP基于PHPExcel导入Excel文件的方法
2014/10/15 PHP
php自动获取关键字的方法
2015/01/06 PHP
PHP判断是否连接上网络的方法
2015/07/01 PHP
PHP自定义函数实现格式化秒的方法
2016/09/14 PHP
Thinkphp5框架中引入Markdown编辑器操作示例
2020/06/03 PHP
PHP日期和时间函数的使用示例详解
2020/08/06 PHP
JQuery UI的拖拽功能实现方法小结
2012/03/14 Javascript
javascript实现在某个元素上阻止鼠标右键事件的方法和实例
2014/08/12 Javascript
JQuery控制Radio选中方法分析
2015/05/29 Javascript
js图片切换具体实现代码
2016/10/13 Javascript
Servlet实现文件上传,可多文件上传示例
2016/12/05 Javascript
bootstrap table单元格新增行并编辑
2017/05/19 Javascript
关于HTML5的data-*自定义属性的总结
2018/05/05 Javascript
vue的传参方式汇总和router使用技巧
2018/05/22 Javascript
vue 实现边输入边搜索功能的实例讲解
2018/09/16 Javascript
js自定义input文件上传样式
2018/10/26 Javascript
JS实现点击按钮随机生成可拖动的不同颜色块示例
2019/01/30 Javascript
vue-router的两种模式的区别
2019/05/30 Javascript
Python的Twisted框架中使用Deferred对象来管理回调函数
2016/05/25 Python
Python元组操作实例分析【创建、赋值、更新、删除等】
2017/07/24 Python
python 监听salt job状态,并任务数据推送到redis中的方法
2019/01/14 Python
Django Admin中增加导出CSV功能过程解析
2019/09/04 Python
ipad上运行python的方法步骤
2019/10/12 Python
Python数据可视化:顶级绘图库plotly详解
2019/12/07 Python
python离线安装外部依赖包的实现
2020/02/13 Python
推荐值得学习的12款python-web开发框架
2020/08/10 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
Canvas与Image互相转换示例代码
2013/08/09 HTML / CSS
HTML5中原生的右键菜单创建方法
2016/06/28 HTML / CSS
英国最好的包装供应商:Priory Direct
2019/12/17 全球购物
质量工程师岗位职责
2013/11/16 职场文书
中级会计职业生涯规划范文
2014/01/16 职场文书
精神文明建设汇报材料
2014/12/24 职场文书
为什么不建议在go项目中使用init()
2021/04/12 Golang