JavaScript-数组去重由慢到快由繁到简演化

 

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");

==> VM325:3 test: 108025.815ms (比较数目越多,差距越大,更好选择)

转自: https://segmentfault.com/a/1190000006632291

作者: xzavier

160819、JavaScript-数组去重由慢到快由繁到简的更多相关文章

  1. JavaScript-数组去重由慢到快由繁到简

    indexOf去重 Array.prototype.unique1 = function() { var arr = []; for (var i = 0; i < this.length; i ...

  2. JavaScript数组去重方法及测试结果

    最近看到一些人的去面试web前端,都说碰到过问JavaScript数组去重的问题,我也学习了一下做下总结. 实际上最有代表性也就三种方法:数组双重循环,对象哈希,排序后去重. 这三种方法我都做了性能测 ...

  3. JavaScript 数组去重方法总结

    1.遍历数组法: 这应该是最简单的去重方法(实现思路:新建一新数组,遍历数组,值不在新数组就加入该新数组中) // 遍历数组去重法 function unique(arr){ var _arr = [ ...

  4. 也谈面试必备问题之 JavaScript 数组去重

    Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  5. javascript数组去重算法-----3

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. javascript数组去重算法-----2

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. javascript数组去重算法-----1

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. javascript数组去重算法-----5

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. javascript数组去重算法-----4(另一种写法__2)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. 使用zbar 解码二维码 条形码

    #!/usr/bin/env python # coding: u8 import os import zbar import Image import urllib import uuid def ...

  2. ssh中使用spring的集成quartz 编写定时任务

    之前没有使用框架开发时对于开发定时任务都是 使用java的原声timer类,重写线程的run方法跑要执行的任务.刚刚换的新公司,项目使用ssh2,目前该项目中的定时任务的使用spirng集成的quar ...

  3. linux c中select使用技巧——计时器(转)

    通过本文你会了解到: 1. select()原型及参数说明 2. select()应用情景 3. select()注意事项 4. select()作定时器 原型 int select(int nfds ...

  4. 【Datastage】NULL VALUE TO A NOT NULL VALUE

    使用ds是报错如上图: 造成这个问题的原因是: 在写SQL时候没有给字段别名与DS中对应一致 例如有下表: CREATE TABLE DataInfo( ID_1 ), ID_2 ) ) CREATE ...

  5. 【DB2】DB2中rank(),dense_rank(),row_number()的用法

    1.准备测试数据 DROP TABLE oliver_1; ),SUB_NO ),SCORE int); ,,); ,,); ,,); ,,); ,,); ,,); 2.详解rank(),dense_ ...

  6. 【MyBatis学习11】MyBatis中的延迟加载

    1. 什么是延迟加载 举个例子:如果查询订单并且关联查询用户信息.如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息.把对用户信息的按需去查询就是延迟加载. 所以延迟加载即先从单表 ...

  7. 应用phpexcel导出excel文件后打不开的问题解决方法

    应用phpexcel导出excel文件后打不开,提示“文件格式或文件扩展名无效,请确定文件未损坏,并且文件扩展名与文件的格式匹配”. 试了以下方法: 1.首先区分文件格式是2003,还是2007. 参 ...

  8. Redis之最大内存置换策略

    0.前言 Redis默认最大内存大小是应用程序可访问的内存大小, 32位windows下是2GB, linux下是3GB. 64位下可以访问的内存为2^64字节, Redis提供了maxmemory字 ...

  9. Java 8里 Stream和parallelStream的区别

    Java中Stream和parallelStream,前者是单管,后者是多管,运行时间上做一个小对比,直接上代码: /** * * @author zhangy6 * <p>对比Strea ...

  10. 【从0開始Tornado建站】0.9版本号python站点代码开源--持续更新中

            从5月份開始[从0開始Tornado建站]这个专栏,開始一点一点把这个分类兴趣站点弄起来,从无到有的过程也是令人兴奋的:-) 国庆的时候等待备案然后上线,如今站点域名为ustchack ...