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 相关文章推荐
DOMAssitant最新版 DOMAssistant 2.5发布
Dec 25 Javascript
js clearInterval()方法的定义和用法
Nov 11 Javascript
AngularJS指令详解及示例代码
Aug 16 Javascript
Javascript中构造函数要注意的一些坑
Jan 23 Javascript
微信小程序 判断手机号的实现代码
Apr 19 Javascript
使用jQuery实现购物车结算功能
Aug 15 jQuery
jQuery插件DataTables分页开发心得体会
Aug 22 jQuery
AngularJS基于http请求实现下载php生成的excel文件功能示例
Jan 23 Javascript
JavaScript事件委托原理与用法实例分析
Jun 07 Javascript
vue-cli 首屏加载优化问题
Nov 06 Javascript
详解CommonJS和ES6模块循环加载处理的区别
Dec 26 Javascript
详解vue 中 scoped 样式作用域的规则
Sep 14 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
Syphon 秘笈
2021/03/03 冲泡冲煮
php下使用无限生命期Session的方法
2007/03/16 PHP
php学习之运算符相关概念
2011/06/09 PHP
Mysql中分页查询的两个解决方法比较
2013/05/02 PHP
php实现插入数组但不影响原有顺序的方法
2015/03/27 PHP
如何通过Linux命令行使用和运行PHP脚本
2015/07/29 PHP
JavaScript mapreduce工作原理简析
2012/11/25 Javascript
利用javascript实现web页面中指定区域打印
2013/10/30 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
2014/01/14 Javascript
jQuery给动态添加的元素绑定事件的方法
2015/03/09 Javascript
Js调用Java方法并互相传参的简单实例
2016/08/11 Javascript
node.js实现快速截图
2016/08/27 Javascript
深入浅析JS是按值传递还是按引用传递(推荐)
2016/09/18 Javascript
使用微信小程序开发前端【快速入门】
2016/12/05 Javascript
设置jquery UI 控件的大小方法
2016/12/12 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
老生常谈javascript中逻辑运算符&amp;&amp;和||的返回值问题
2017/04/13 Javascript
微信小程序图片横向左右滑动案例
2017/05/19 Javascript
angularjs1.5 组件内用函数向外传值的实例
2018/09/30 Javascript
[01:14]TI珍贵瞬间系列(六):冠军
2020/08/30 DOTA
用Python操作字符串之rindex()方法的使用
2015/05/19 Python
详解Python操作RabbitMQ服务器消息队列的远程结果返回
2016/06/30 Python
Python文件操作中进行字符串替换的方法(保存到新文件/当前文件)
2019/06/28 Python
Python获取好友地区分布及好友性别分布情况代码详解
2019/07/10 Python
python3下pygame如何实现显示中文
2020/01/11 Python
Tensorflow不支持AVX2指令集的解决方法
2020/02/03 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
分享29个基于Bootstrap的HTML5响应式网页设计模板
2015/11/19 HTML / CSS
基于canvas使用贝塞尔曲线平滑拟合折线段的方法
2018/01/10 HTML / CSS
英国在线定做百叶窗网站:Make My Blinds
2020/08/17 全球购物
简单介绍Object类的功能、常用方法
2013/10/02 面试题
学习十八大报告感言
2014/02/04 职场文书
煤矿安全承诺书
2014/05/22 职场文书
纪检干部现实表现材料
2014/08/21 职场文书
一篇合格的广告文案,其主要目的是什么?
2019/07/12 职场文书
CentOS MySql8 远程连接实战
2022/04/19 MySQL