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 相关文章推荐
jQuery 技巧小结
Apr 02 Javascript
jQuery下通过$.browser来判断浏览器.
Apr 05 Javascript
jquery ajax中使用jsonp的限制解决方法
Nov 22 Javascript
js实现俄罗斯方块小游戏分享
Jan 31 Javascript
删除Javascript Object中间的key
Nov 18 Javascript
javascript数据类型验证方法
Dec 31 Javascript
JavaScript实现的搜索及高亮显示功能示例
Aug 14 Javascript
Angular2进阶之如何避免Dom误区
Apr 02 Javascript
Vue 按键修饰符处理事件的方法
May 04 Javascript
如何理解Vue的v-model指令的使用方法
Jul 19 Javascript
基于Vue实现关键词实时搜索高亮显示关键词
Jul 21 Javascript
Vue 禁用浏览器的前进后退操作
Sep 04 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下读取文本文件的代码
2008/07/02 PHP
php 中奖概率算法实现代码
2017/01/25 PHP
$()JS小技巧
2007/07/21 Javascript
JQuery操作表格(隔行着色,高亮显示,筛选数据)
2012/02/23 Javascript
简单实用的全选反选按钮例子
2013/10/18 Javascript
JavaScript严格模式禁用With语句的原因
2014/10/20 Javascript
jquery判断至少有一个checkbox被选中的方法
2015/06/05 Javascript
JQuery中DOM加载与事件执行实例分析
2015/06/13 Javascript
第七章之菜单按钮图标组件
2016/04/25 Javascript
Vue.js -- 过滤器使用总结
2017/02/18 Javascript
JavaScript面向对象继承原理与实现方法分析
2018/08/09 Javascript
vue 解决在微信内置浏览器中调用支付宝支付的情况
2020/11/09 Javascript
解决vue页面刷新,数据丢失的问题
2020/11/24 Vue.js
[01:19:46]EG vs Secret 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
跟老齐学Python之从格式化表达式到方法
2014/09/28 Python
Python的Django框架中URLconf相关的一些技巧整理
2015/07/18 Python
python之PyMongo使用总结
2017/05/26 Python
Python配置mysql的教程(推荐)
2017/10/13 Python
Python反射的用法实例分析
2018/02/11 Python
在CMD命令行中运行python脚本的方法
2018/05/12 Python
python分块读取大数据,避免内存不足的方法
2018/12/10 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
python判断无向图环是否存在的示例
2019/11/22 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
2020/06/28 Python
利用Pycharm + Django搭建一个简单Python Web项目的步骤
2020/10/22 Python
Python中Qslider控件实操详解
2021/02/20 Python
H5混合开发app如何升级的方法
2018/01/10 HTML / CSS
放飞蜻蜓反思
2014/02/05 职场文书
大三学生英语考试作弊检讨书
2015/01/01 职场文书
招标保密承诺书
2015/01/20 职场文书
介绍信模板
2015/01/31 职场文书
求职自荐信范文(优秀篇)
2015/03/27 职场文书
在人间读书笔记
2015/06/30 职场文书
Java并发编程之详解CyclicBarrier线程同步
2021/06/23 Java/Android
Java 超详细讲解hashCode方法
2022/04/07 Java/Android
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android