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 相关文章推荐
解决表单中第一个非隐藏的元素获得焦点的一个方案
Oct 26 Javascript
JavaScript 学习笔记(十二) dom
Jan 21 Javascript
JQuery入门——事件切换之hover()方法应用介绍
Feb 05 Javascript
cookie的secure属性详解
Apr 08 Javascript
jQuery聚合函数实例
May 21 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
Aug 05 Javascript
chrome下判断点击input上标签还是其余标签的实现方法
Sep 18 Javascript
js前端解决跨域问题的8种方案(最新最全)
Nov 18 Javascript
基于Angular.js实现的触摸滑动动画实例代码
Feb 19 Javascript
简化vuex的状态管理方案的方法
Jun 02 Javascript
微信小程序mpvue点击按钮获取button值的方法
May 29 Javascript
vuex根据不同的用户权限展示不同的路由列表功能
Sep 20 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学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠
2015/09/30 PHP
php cookie 详解使用实例
2016/11/03 PHP
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
js substr、substring和slice使用说明小记
2011/09/15 Javascript
jQuery插件原来如此简单 jQuery插件的机制及实战
2012/02/07 Javascript
解析Jquery的LigerUI如何实现文件上传
2013/07/09 Javascript
最全的Javascript编码规范(推荐)
2016/06/22 Javascript
nodejs读写json文件的简单方法(必看)
2017/03/09 NodeJs
微信小程序实现给循环列表添加点击样式实例
2017/04/26 Javascript
vue v-on监听事件详解
2017/05/17 Javascript
浅谈angularJS的$watch失效问题的解决方案
2017/08/11 Javascript
AngularJS实现controller控制器间共享数据的方法示例
2017/10/30 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
使用vue-cli打包过程中的步骤以及问题的解决
2018/05/08 Javascript
关于Vue组件库开发详析
2018/07/01 Javascript
微信小程序实现购物页面左右联动
2019/02/15 Javascript
JavaScript函数式编程(Functional Programming)箭头函数(Arrow functions)用法分析
2019/05/22 Javascript
[04:13]2014DOTA2国际邀请赛 专访DC目前形势不容乐观
2014/07/12 DOTA
[01:13:59]LGD vs Mineski Supermajor 胜者组 BO3 第三场 6.5
2018/06/06 DOTA
python线程池的实现实例
2013/11/18 Python
python中列表元素连接方法join用法实例
2015/04/07 Python
探究Python中isalnum()方法的使用
2015/05/18 Python
python版本的读写锁操作方法
2016/04/25 Python
Python将图片转换为字符画的方法
2020/06/16 Python
python绘制直方图和密度图的实例
2019/07/08 Python
利用anaconda作为python的依赖库管理方法
2019/08/13 Python
大家都说好用的Python命令行库click的使用
2019/11/07 Python
python分布式编程实现过程解析
2019/11/08 Python
Python 给下载文件显示进度条和下载时间的实现
2020/04/02 Python
Python 字典一个键对应多个值的方法
2020/09/29 Python
Baby Tulai澳大利亚:美国婴儿背带品牌
2018/10/15 全球购物
德国家具折扣店:POCO
2020/02/28 全球购物
商务日语专业毕业生求职信
2013/10/26 职场文书
普通员工辞职信
2014/01/17 职场文书
公司周年庆活动方案
2014/08/25 职场文书