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-数组去重由慢到快由繁到简的更多相关文章

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

    JavaScript-数组去重由慢到快由繁到简演化   indexOf去重 Array.prototype.unique1 = function() { var arr = []; for (var ...

  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. 实战MEF(5):导出元数据

    如何理解元数 我们可以把元数据理解为随类型一起导出的附加信息.有时候我们会考虑,把元数据随类型一并导出,增加一些说明,使得我们在导入的时候,可以多一些筛选条件. 默认的类型导出带有元数据吗 上面的内容 ...

  2. jQuery的Internal DSL

    JQuery的核心理念是write less,do more(写的更少,做的更多),那么链式方法的设计与这个核心理念不谋而合.那么从深层次考虑这种设计其实就是一种Internal DSL. DSL是指 ...

  3. 【技巧篇】解决悬浮的<header>、<footer>遮挡内容的处理技巧

    引言   在现在的前端页面中,尤其是移动端,经常会需要将<header>或者是<footer>模块悬浮出来,跟随页面的滑动保持定位在页面的最上方或者是最下方,如下图所示. “回 ...

  4. 项目安排(离散化+DP)

    题目来源:网易有道2013年校园招聘面试二面试题 题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的 ...

  5. YII 的源码分析(二)

    上一篇简单分析了一下yii的流程,从创建一个应用,到屏幕上输出结果.这一次我来一个稍复杂一点的,重点在输出上,不再是简单的一行"hello world",而是要经过view(视图) ...

  6. Pointer is missing a nullability type specifier (__nonnull or __nullable)

    我们都知道在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!.而在Objective-C中则没有这一区分,view即可表示这个对象是 ...

  7. iOS开发使用半透明模糊效果方法整理

    虽然iOS很早就支持使用模糊效果对图片等进行处理,但尤其在iOS7以后,半透明模糊效果得到大范围广泛使用.包括今年最新发布的iOS8也沿袭了这一设计,甚至在OS X 10.10版Yosemite中也开 ...

  8. js实现可拖拽的div

    前言 下午忙里偷闲想写一个可拖拽的例子,留在脑海里一直都是三个事件mouseDown,mouseUp,mouseMove, 但从没有动手实践过,今天想起了自己实践了并学习了张鑫旭的demo实现. 学习 ...

  9. Delphi TListView刷新闪烁问题

    应用场景 TListView可以动态选择列并显示而且列宽度也要保存,加载数据ListView会出现N次闪烁 步骤一: 选择要显示列: 点击"确定"按钮,显示下图 步骤二: 界面会出 ...

  10. uploadify上传错误:uncaught exception: call to startUpload failed原因

    这个不是什么tab的问题,而是可能有多个上传的div或者input(含有相同的name或者ID)导致的 如果有两个不同的上传按钮,那么他们的name,id要设置得不一样. <div id='to ...