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. LInux——安装Apache

    在安装Apache的httpd的时候经常会遇到: configure: error: APR not found .  Please read the documentation. configure ...

  2. 远程调用——hessian使用入门

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...

  3. WP8数据存储--独立存储设置

    <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinition ...

  4. Linux 时间修改--date -s命令

    Linux 时间修改 不重启修改时区 一.修改linux的时间root使用date指令:date -s1.只修改日期,不修改时间,输入:Linux代码 1. date -s 2007-08-03 da ...

  5. Pycharm 安装scrapy

    因为scrapy需要依赖第三方的包,所以直接使用Pycharm安装Scrapy包无法安装成功.网上已经有很多使用cmd安装scrapy的优秀教程,此处不再介绍. 基于下图所示的结构之下向上即可完成sc ...

  6. Python pip install Twisted 出错“Command "c:\python37\python.exe -u -c "import setuptools, tokenize;__file__='C:...\\Twisted\\setup.py'.... failed with error code 1 in C:... \\Twisted"

    如标题所说: python版本是目前最新的3.7.1 结果发现并不是环境问题,而是直接 pip install Twisted 安装的包不兼容 需要手动下载兼容的扩展包Twisted-18.9.0-c ...

  7. nodejs 获取指定路径下所有的文件夹名

    示例:获取 ./components 下所有的文件夹名称 let components = [] const files = fs.readdirSync('./components') files. ...

  8. linux文件系统调用(1)---mount

    术语表: struct mount:挂载点 struct mountpoint:挂载点节点 struct vfsmount:挂载项 源文件系统:用户将要挂载的文件系统 目的文件系统:挂载源文件系统的文 ...

  9. leetCode 30.Substring with Concatenation of All Words (words中全部子串相连) 解题思路和方法

    Substring with Concatenation of All Words You are given a string, s, and a list of words, words, tha ...

  10. layui表格的批量删除功能

    // 批量删除功能 // 1.得到table选中行内容 // 2.得到删除需要的唯一值,一般是id; // 3.将所要删除的项加入到数组中: // 4.判断是否选中: // 5.发送ajax请求,并附 ...