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 相关文章推荐
使用Mootools动态添加Css样式表代码,兼容各浏览器
Dec 12 Javascript
javascript获取所有同类checkbox选项(实例代码)
Nov 07 Javascript
javascript框架设计读书笔记之模块加载系统
Dec 02 Javascript
jQuery实现的进度条效果
Jul 15 Javascript
JQuery标签页效果实例详解
Dec 24 Javascript
jQuery实现的文字hover颜色渐变效果实例
Feb 20 Javascript
JavaScript的模块化开发框架Sea.js上手指南
May 12 Javascript
jQuery实现动态文字搜索功能
Jan 05 Javascript
简单的jQuery拖拽排序效果的实现(增强动态)
Feb 09 Javascript
js设置随机切换背景图片的简单实例
Nov 12 Javascript
vue源码入口文件分析(推荐)
Jan 30 Javascript
Vue 构造选项 - 进阶使用说明
Aug 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
关于我转生变成史莱姆这档事:第二季PV上线,萌王2021年回归
2020/05/06 日漫
不用数据库的多用户文件自由上传投票系统(2)
2006/10/09 PHP
ThinkPHP 404页面的设置方法
2015/01/14 PHP
PHP curl使用实例
2015/07/02 PHP
PHP队列场景以及实现代码实例详解
2021/02/26 PHP
javascript 设计模式之单体模式 面向对象学习基础
2010/04/18 Javascript
有道JavaScript监听浏览器的问题
2010/06/23 Javascript
jQuery 开发者应该注意的9个错误
2012/05/03 Javascript
网站404页面3秒后跳到首页的实例代码
2013/08/16 Javascript
JS实现图片无间断滚动代码汇总
2014/07/30 Javascript
javascript中HTMLDOM操作详解
2014/12/11 Javascript
JavaScript从数组中删除指定值元素的方法
2015/03/18 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
2015/10/23 Javascript
使用Javascript写的2048小游戏
2015/11/25 Javascript
js判断上传文件后缀名是否合法
2016/01/28 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
2016/02/26 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
如何正确理解javascript的模块化
2017/03/02 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
2018/10/18 Javascript
JS无限级导航菜单实现方法
2019/01/05 Javascript
浅析vue插槽和作用域插槽的理解
2019/04/22 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
Node.js HTTP服务器中的文件、图片上传的方法
2019/09/23 Javascript
vue中使用极验验证码的方法(附demo)
2019/12/04 Javascript
[04:29]【TI9采访】OG.N0tail在胜者组决赛后接受采访
2019/08/25 DOTA
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
详解python之协程gevent模块
2018/06/14 Python
40个你可能不知道的Python技巧附代码
2020/01/29 Python
深入浅析pycharm中 Make available to all projects的含义
2020/09/15 Python
python两种获取剪贴板内容的方法
2020/11/06 Python
关于前端上传文件全面基础扫盲贴(入门)
2019/08/01 HTML / CSS
使用phonegap克隆和删除联系人的实现方法
2017/03/31 HTML / CSS
盛大笔试题
2016/11/05 面试题
运动会400米加油稿(8篇)
2014/09/22 职场文书
2017春节晚会开幕词
2016/03/03 职场文书
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL