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 相关文章推荐
Prototype PeriodicalExecuter对象 学习
Jul 19 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字
Jan 23 Javascript
javascript修改IMG标签的src问题
Mar 28 Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
Sep 21 Javascript
Bootstrap基本组件学习笔记之导航(10)
Dec 07 Javascript
JS焦点图,JS 多个页面放多个焦点图的实例
Dec 08 Javascript
ES6中Proxy代理用法实例浅析
Apr 06 Javascript
Angular.JS通过指令操作DOM的方法
May 10 Javascript
ligerUI---ListBox(列表框可移动的实例)
Nov 28 Javascript
jQuery zTree插件快速实现目录树
Aug 16 jQuery
Vue退出登录时清空缓存的实现
Nov 12 Javascript
JS深入学习之数组对象排序操作示例
May 01 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
第1次亲密接触PHP5(1)
2006/10/09 PHP
php function用法如何递归及return和echo区别
2014/03/07 PHP
PHP 开发者该知道的 5 个 Composer 小技巧
2016/02/03 PHP
深入理解PHP中mt_rand()随机数的安全
2017/10/12 PHP
简单的代码实现jquery定时器
2014/01/03 Javascript
利用javascript打开模态对话框(示例代码)
2014/01/11 Javascript
jQuery 获取、设置HTML或TEXT内容的两种方法
2014/05/23 Javascript
一款由jquery实现的整屏切换特效
2014/09/15 Javascript
NodeJS使用jQuery选择器操作DOM
2015/02/13 NodeJs
谈谈我对JavaScript中typeof和instanceof的深入理解
2015/12/25 Javascript
限制复选框最多选择项的实现代码
2016/05/30 Javascript
基于JS实现导航条flash导航条
2016/06/17 Javascript
JS 日期与时间戮相互转化的简单实例
2016/06/22 Javascript
jQuery实现的省市县三级联动菜单效果完整实例
2016/08/01 Javascript
js print打印网页指定区域内容的简单实例
2016/11/01 Javascript
bootstrap可编辑下拉框jquery.editable-select
2017/10/12 jQuery
vue表单验证之禁止input输入框输入空格
2020/12/03 Vue.js
Python中__call__用法实例
2014/08/29 Python
python实现去除下载电影和电视剧文件名中的多余字符的方法
2014/09/23 Python
Python线程中对join方法的运用的教程
2015/04/09 Python
复习Python中的字符串知识点
2015/04/14 Python
Python爬虫框架Scrapy实战之批量抓取招聘信息
2015/08/07 Python
Python第三方库xlrd/xlwt的安装与读写Excel表格
2017/01/21 Python
Collatz 序列、逗号代码、字符图网格实例
2017/06/22 Python
Selenium+Python 自动化操控登录界面实例(有简单验证码图片校验)
2019/06/28 Python
python如何将多个PDF进行合并
2019/08/13 Python
Python3 全自动更新已安装的模块实现
2020/01/06 Python
Python基础之字符串常见操作经典实例详解
2020/02/26 Python
美国马匹用品和骑马配件购物网站:Horse.com
2018/01/08 全球购物
俄罗斯运动鞋商店:Sneakerhead
2018/05/10 全球购物
面试后感谢信怎么写
2014/02/01 职场文书
聚会通知怎么写
2015/04/23 职场文书
2015年平安创建工作总结
2015/04/29 职场文书
2016年社区六一儿童节活动总结
2016/04/06 职场文书
vue使用refs获取嵌套组件中的值过程
2022/03/31 Vue.js
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技