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 相关文章推荐
JScript 脚本实现文件下载 一般用于下载木马
Oct 29 Javascript
JavaScript 轻松搞定快捷留言功能 只需一行代码
Apr 01 Javascript
JQUERY的属性选择符和自定义选择符使用方法(二)
Apr 07 Javascript
js获取数组的最后一个元素
Apr 14 Javascript
用JS实现图片轮播效果代码(一)
Jun 26 Javascript
关于原生js中bind函数的简单实现
Aug 10 Javascript
angular.js之路由的选择方法
Sep 24 Javascript
使用vue.js编写蓝色拼图小游戏
Mar 17 Javascript
关于Node.js的events.EventEmitter用法介绍
Apr 01 Javascript
JS匹配日期和时间的正则表达式示例
May 12 Javascript
Vue中的无限加载vue-infinite-loading的方法
Apr 08 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
Aug 03 jQuery
针对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
超级简单的发送邮件程序
2006/10/09 PHP
PHP+DBM的同学录程序(4)
2006/10/09 PHP
有关php运算符的知识大全
2011/11/03 PHP
PHP文件系统管理(实例讲解)
2017/09/19 PHP
分享8个Laravel模型时间戳使用技巧小结
2020/02/12 PHP
让回调函数 showResponse 也带上参数的代码
2007/08/13 Javascript
js form 验证函数 当前比较流行的错误提示
2009/06/23 Javascript
Javascript学习笔记2 函数
2010/01/11 Javascript
js中获取事件对象的方法小结
2011/03/13 Javascript
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
JavaScript简单下拉菜单实例代码
2015/09/07 Javascript
AngularJS 整理一些优化的小技巧
2016/08/18 Javascript
vue2实现数据请求显示loading图
2017/11/28 Javascript
vue实现打印功能的两种方法
2018/09/07 Javascript
ES6函数和数组用法实例分析
2020/05/23 Javascript
openlayers4.6.5实现距离量测和面积量测
2020/09/25 Javascript
[01:10:03]OG vs EG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
[02:22]完美世界DOTA2联赛PWL S3 集锦第一期
2020/12/15 DOTA
Python实现身份证号码解析
2015/09/01 Python
python操作redis方法总结
2018/06/06 Python
python如何求100以内的素数
2020/05/27 Python
15个应该掌握的Jupyter Notebook使用技巧(小结)
2020/09/23 Python
CSS3常用的几种颜色渐变模式总结
2016/11/18 HTML / CSS
HTML5之SVG 2D入门10—滤镜的定义及使用
2013/01/30 HTML / CSS
伦敦最著名的老字号百货公司:Selfridges(塞尔福里奇百货)
2016/07/25 全球购物
美国电视购物HSN官网:HSN
2016/09/07 全球购物
幼师岗位求职简历的自荐信格式
2013/09/21 职场文书
应聘教师推荐信
2013/10/31 职场文书
房屋租赁协议书
2014/04/10 职场文书
土建施工员岗位职责
2014/07/16 职场文书
装修施工安全责任书
2014/07/24 职场文书
2015年乡镇环保工作总结
2015/04/22 职场文书
超市员工辞职信范文
2015/05/12 职场文书
2015年民兵整组工作总结
2015/07/24 职场文书
前端canvas中物体边框和控制点的实现示例
2022/08/05 Javascript