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 相关文章推荐
css配合jquery美化 select
Nov 29 Javascript
javascript实现简单的Map示例介绍
Dec 23 Javascript
JavaScript实现网页加载进度条代码超简单
Sep 21 Javascript
javascript RegExp 使用说明
May 21 Javascript
BootStrap selectpicker
Jun 20 Javascript
jquery mobile实现可折叠的导航按钮
Mar 11 Javascript
Angular 2 利用Router事件和Title实现动态页面标题的方法
Aug 23 Javascript
phantomjs导出html到pdf的方法总结
Oct 19 Javascript
妙用缓存调用链实现JS方法的重载
Apr 30 Javascript
JavaScript常见事件处理程序实例总结
Jan 05 Javascript
浅析Angular 实现一个repeat指令的方法
Jul 21 Javascript
vue使用codemirror的两种用法
Aug 27 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 adodb连接mssql解决乱码问题
2009/06/12 PHP
PHP及Zend Engine的线程安全模型分析
2011/11/10 PHP
php tp验证表单与自动填充函数代码
2012/02/22 PHP
CI框架源码阅读,系统常量文件constants.php的配置
2013/02/28 PHP
解析php取整的几种方式
2013/06/25 PHP
使用CodeIgniter的类库做图片上传
2014/06/12 PHP
php计算指定目录下文件占用空间的方法
2015/03/13 PHP
解决安装WampServer时提示缺少msvcr110.dll文件的问题
2017/07/09 PHP
php微信公众号开发之翻页查询
2018/10/20 PHP
Javascript SHA-1:Secure Hash Algorithm
2006/12/20 Javascript
JavaScript 布尔操作符解析  &amp;&amp; || !
2012/08/10 Javascript
控制input输入框中提示信息的显示和隐藏的方法
2014/02/12 Javascript
JS实现静止元素自动移动示例
2014/04/14 Javascript
原生js封装自定义滚动条
2017/03/24 Javascript
jsTree事件和交互以及插件plugins详解
2017/08/29 Javascript
解决vue项目使用font-awesome,build后路径的问题
2018/09/01 Javascript
浅谈layui 绑定form submit提交表单的注意事项
2019/10/25 Javascript
javascript 原型与原型链的理解及应用实例分析
2020/02/10 Javascript
jQuery 实现扁平式小清新导航
2020/07/07 jQuery
React Ant Design树形表格的复杂增删改操作
2020/11/02 Javascript
vue实现拖拽进度条
2021/03/01 Vue.js
[44:43]完美世界DOTA2联赛决赛日 FTD vs GXR 第一场 11.08
2020/11/11 DOTA
Python的Bottle框架的一些使用技巧介绍
2015/04/08 Python
Python3计算三角形的面积代码
2017/12/18 Python
pandas将DataFrame的列变成行索引的方法
2018/04/10 Python
Python检测网络延迟的代码
2018/05/15 Python
Python设计模式之策略模式实例详解
2019/01/21 Python
详解Python中的各种转义符\n\r\t
2019/07/10 Python
python中round函数如何使用
2020/06/19 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
Kathmandu英国网站:新西兰户外运动品牌
2017/03/27 全球购物
Madda Fella官网:美国冒险家服装品牌
2020/01/16 全球购物
意大利顶级奢侈品电商:LUISAVIAROMA(支持中文)
2020/05/26 全球购物
电子商务专业学生的学习自我评价
2013/10/27 职场文书
美丽人生观后感
2015/06/03 职场文书
nginx部署多前端项目的几种方法
2021/05/25 Servers