javascript数组去重的六种方法汇总_javascript技巧
面试前端必须准备的一个问题:怎样去掉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的结构记录已有的元素,这样就可以避免内层循环。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

PHP的array_unique()函数用于去除数组中重复元素,其缺省使用严格相等(===)。我们可以通过自定比较函数来指定去重依据:创建自定比较函数,指定去重的标准(例如根据元素长度);将自定比较函数作为第三个参数传递给array_unique()函数,即可根据指定的标准去除重复元素。

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。
