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 获取select下拉列表值的代码
Sep 07 Javascript
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 Javascript
Extjs4 消息框去掉关闭按钮(类似Ext.Msg.alert)
Apr 02 Javascript
document.documentElement的一些使用技巧
Apr 18 Javascript
jquery 判断滚动条到达了底部和顶端的方法
Apr 02 Javascript
详解js闭包
Sep 02 Javascript
整理AngularJS中的一些常用指令
Jun 16 Javascript
针对初学者的jQuery入门指南
Aug 15 Javascript
微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义实例
Dec 08 Javascript
详解js中Number()、parseInt()和parseFloat()的区别
Dec 20 Javascript
详解开源的JavaScript插件化框架MinimaJS
Oct 26 Javascript
JS+Canvas绘制动态时钟效果
Nov 10 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与c 实现按行读取文件实例代码
2017/01/03 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
2018/06/13 PHP
JavaScript 对象模型 执行模型
2010/10/15 Javascript
基于jquery的jqDnR拖拽溢出的修改
2011/02/12 Javascript
select标记美化--JS式插件、后期加载
2013/04/01 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
判断文档离浏览器顶部的距离的方法
2014/01/08 Javascript
JS获取checkbox的个数简单实例
2016/08/19 Javascript
AngularJS入门教程之Cookies读写操作示例
2016/11/02 Javascript
JS基于正则截取替换特定字符之间字符串操作示例
2017/02/03 Javascript
Ionic3 UI组件之Gallery Modal详解
2017/06/07 Javascript
详解在React中跨组件分发状态的三种方法
2018/08/09 Javascript
Node.js中Koa2在控制台输出请求日志的方法示例
2019/05/02 Javascript
微信小程序定义和调用全局变量globalData的实现
2019/11/01 Javascript
JS对象属性的检测与获取操作实例分析
2020/03/17 Javascript
JavaScript枚举选择jquery插件代码实例
2020/11/17 jQuery
[00:35]TI7不朽珍藏III——寒冰飞龙不朽展示
2017/07/15 DOTA
python实现连接mongodb的方法
2015/05/08 Python
Python ldap实现登录实例代码
2016/09/30 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
2017/08/24 Python
python绘制散点图并标记序号的方法
2018/12/11 Python
DRF跨域后端解决之django-cors-headers的使用
2019/01/27 Python
用python求一个数组的和与平均值的实现方法
2019/06/29 Python
Pytorch实现的手写数字mnist识别功能完整示例
2019/12/13 Python
tensorflow 获取所有variable或tensor的name示例
2020/01/04 Python
Python+Kepler.gl轻松制作酷炫路径动画的实现示例
2020/06/02 Python
Python替换NumPy数组中大于某个值的所有元素实例
2020/06/08 Python
举例详解HTML5中使用JSON格式提交表单
2015/06/16 HTML / CSS
长青弘远的面试题
2012/06/09 面试题
英语自我评价范文
2014/01/24 职场文书
环保公益策划方案
2014/08/15 职场文书
2015试用期转正工作总结
2014/12/12 职场文书
企业党员岗位承诺书
2015/04/27 职场文书
超级礼物观后感
2015/06/15 职场文书
《暗黑破坏神2:重制版》本周进行第一轮A测 目前可官网进行申请报名
2021/04/07 其他游戏