JavaScript数组去重由慢到快由繁到简(优化篇)


Posted in Javascript onAugust 26, 2016

在进行数组操作时往往会遇到去掉重复项的问题,下面简单介绍下数组去重的方法。

indexOf去重

Array.prototype.unique1 = function() {
var arr = [];
for (var i = 0; i < this.length; i++) {
var item = this[i];
if (arr.indexOf(item) === -1) {
arr.push(item);
}
}
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique1(); //[1, 2, 3, "4", 4, "34"]

不过,在 IE6-8 下,数组的 indexOf 方法还不存在(虽然这已经算有点古老的话题了O(∩_∩)O~),但是,程序员就要写一个indexOf方法:

var indexOf = [].indexOf ? function(arr, item) {
return arr.indexOf(item);
} :
function indexOf(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
return i;
}
}
return -1;
}
Array.prototype.unique2 = function() {
var arr = [];
for (var i = 0; i < this.length; i++) {
var item = this[i];
if (arr.indexOf(item) === -1) {
arr.push(item);
}
}
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique2(); //[1, 2, 3, "4", 4, "34"]

indexOf还可以以这样的去重思路:

Array.prototype.unique3 = function(){
var arr = [this[0]]; 
for(var i = 1; i < this.length; i++) 
{
if (this.indexOf(this[i]) == i){
arr.push(this[i]);
} 
}
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique3(); //[1, 2, 3, "4", 4, "34"]

hash去重

以上indexOf正确性没问题,但性能上,两重循环会降低性能。那我们就用hash。

Array.prototype.unique4 = function() {
var arr = [];
var hash = {};
for (var i = 0; i < this.length; i++) {
var item = this[i];
var key = typeof(item) + item
if (hash[key] !== 1) {
arr.push(item);
hash[key] = 1;
}
} 
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique4(); //[1, 2, 3, "4", 4, "34"]

核心是构建了一个 hash 对象来替代 indexOf。空间换时间。注意在 JavaScript 里,对象的键值只能是字符串(当然,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的Hash结构现。),因此需要var key = typeof(item) + item 来区分数值 1 和字符串 '1' 等情况。

那如果你想要'4' 和 4 被认为是相同的话(其他方法同理)

Array.prototype.unique5 = function(){
var arr=[];
var hash={};
for(var i=0,len=this.length;i<len;i++){
if(!hash[this[i]]){ 
arr.push(this[i]);
hash[this[i]]=true;
}
}
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique5(); //[1, 2, 3, "4", "34"]

排序后去重

Array.prototype.unique6 = function(){
this.sort();
var arr = [this[0]];
for(var i = 1; i < this.length; i++){
if( this[i] !== arr[arr.length-1]){
arr.push(this[i]);
}
}
return arr;
}
[1,2,3,'4',3,4,3,1,'34',2].unique6(); //[1, 2, 3, "34", "4", 4]

先把数组排序,然后比较相邻的两个值,排序的时候用的JS原生的sort方法,所以非常快。而这个方法的缺陷只有一点,比较字符时按照字符编码的顺序进行排序。所以会看到10排在2前面这种情况。不过在去重中不影响。不过,解决sort的这个问题,是sort方法接受一个参数,这个参数是一个方法:

function compare(value1,value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
[1,2,5,2,10,3,20].sort(compare); //[1, 2, 2, 3, 5, 10, 20]

Set去重

ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。现在浏览器正在全面支持,服务端的node也已经支持。

Array.prototype.unique7 = function(){
return Array.from(new Set(this));
}
[1,2,3,'4',3,4,3,1,'34',2].unique7(); //[1, 2, 3, "4", 4, "34"]

方法库

推荐一个方法库Underscore.js,在node或浏览器js中都很受欢迎。

const _ = require('underscore');
_.uniq([1, 2, 1, 3, 1, 4]); //[1, 2, 3, 4]

测试时间

以上方法均可以用一个简单的方法去测试一下所耗费的时间,然后对各个方法做比较择优:

console.time("test");
[1,2,3,'4',3,4,3,1,'34',2].unique7();
console.timeEnd("test");
==> VM314:3 test: 0.378ms

让数据变得大一点,就随机创建100万个数:

var arr = [];
var num = 0;
for(var i = 0; i < 1000000; i++){
num = Math.floor(Math.random()*100);
arr.push(num);
}
console.time("test");
arr.unique7();
console.timeEnd("test");

以上所述是小编给大家介绍的JavaScript数组去重由慢到快由繁到简,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 对象的定义方法
Jan 10 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
Jan 11 Javascript
用jquery统计子菜单的条数示例代码
Oct 18 Javascript
高性能JavaScript模板引擎实现原理详解
Feb 05 Javascript
JavaScript中string对象
Jun 12 Javascript
深入探究使JavaScript动画流畅的一些方法
Jun 30 Javascript
基于CSS3和jQuery实现跟随鼠标方位的Hover特效
Jul 25 Javascript
JavaScript微信定位功能实现方法
Nov 29 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
Dec 30 Javascript
jQuery实现base64前台加密解密功能详解
Aug 29 jQuery
微信小程序如何获取手机验证码
Nov 04 Javascript
Element Input输入框的使用方法
Jul 26 Javascript
针对JavaScript中this指向的简单理解
Aug 26 #Javascript
轻松掌握JavaScript代理模式
Aug 26 #Javascript
轻松掌握JavaScript单例模式
Aug 25 #Javascript
很酷的星级评分系统原生JS实现
Aug 25 #Javascript
jQuery 利用$.ajax 时获取原生XMLHttpRequest 对象的方法
Aug 25 #Javascript
轻松掌握JavaScript策略模式
Aug 25 #Javascript
Javascript 6里的4个新语法
Aug 25 #Javascript
You might like
php mb_substr()函数截取中文字符串应用示例
2014/07/29 PHP
php中magic_quotes_gpc对unserialize的影响分析
2014/12/16 PHP
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
2016/07/21 PHP
php实现给二维数组中所有一维数组添加值的方法
2017/02/04 PHP
Javascript 闭包引起的IE内存泄露分析
2012/05/23 Javascript
解析John Resig Simple JavaScript Inheritance代码
2012/12/03 Javascript
JS操作图片(增,删,改) 例子
2013/04/17 Javascript
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
javascript中的throttle和debounce浅析
2014/06/06 Javascript
jQuery中nextAll()方法用法实例
2015/01/07 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
详解JavaScript中的every()方法
2015/06/08 Javascript
jQuery.deferred对象使用详解
2016/03/18 Javascript
JavaScript获取URL参数的方法之一
2017/03/24 Javascript
整理关于Bootstrap警示框的慕课笔记
2017/03/29 Javascript
vue将单页面改造成多页面应用的方法
2018/11/25 Javascript
关于微信小程序获取小程序码并接受buffer流保存为图片的方法
2019/06/07 Javascript
小程序表单认证布局及验证详解
2020/06/19 Javascript
基于vue--key值的特殊用处详解
2020/07/31 Javascript
Vue实现手机号、验证码登录(60s禁用倒计时)
2020/12/19 Vue.js
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
python抽取指定url页面的title方法
2018/05/11 Python
Python爬虫 scrapy框架爬取某招聘网存入mongodb解析
2019/07/31 Python
Pycharm连接远程服务器并实现远程调试的实现
2019/08/02 Python
关于Flask项目无法使用公网IP访问的解决方式
2019/11/19 Python
基于Python的一个自动录入表格的小程序
2020/08/05 Python
怎样让char类型的东西转换成int类型
2013/12/09 面试题
如何理解transaction事务的概念
2015/05/27 面试题
信用卡逾期证明示例
2014/09/13 职场文书
2014医学院领导干部四风对照检查材料思想汇报
2014/09/16 职场文书
不遵守课堂纪律的检讨书
2014/09/24 职场文书
2014年酒店工作总结范文
2014/11/17 职场文书
员工离职通知函
2015/04/25 职场文书
2015年学校政教工作总结
2015/07/20 职场文书
动画「半妖的夜叉姬」新BD特典图公开
2022/03/22 日漫
html用代码制作虚线框怎么做? dw制作虚线圆圈的技巧
2022/12/24 HTML / CSS