开发数据平台的时候遇到了性能瓶颈;
当我用lodash的uniq方法去重一个很大的数组的时候,性能非常的差,
后来在stackoverflow上找到了很多神奇的去重技巧:
例如我目前用的快得让人无法相信的奇怪算法:
1 2 3 4
| var array = [1, 2, 3, 4, 5, 6, 2, 3, 4]; var obj = {}; array.forEach(function(id){obj[id] = true}); array = Object.keys(obj);
|
这个利用了对象的key是uniq的这种性质。
还有一种思想类似的,可读性也类似的:
1 2 3 4 5 6
| Array.prototype.getUnique = function() { var o = {}, a = [] for (var i = 0; i < this.length; i++) o[this[i]] = 1 for (var e in o) a.push(e) return a }
|
另一种是利用了对象具有的hasOwnProperty方法来快速查询重复元素的,这种也非常快,
速度与第一种不相上下:
1 2 3 4 5 6 7 8 9 10 11
| Array.prototype.getUnique = function(){ var u = {}, a = []; for(var i = 0, l = this.length; i < l; ++i){ if(u.hasOwnProperty(this[i])) { continue; } a.push(this[i]); u[this[i]] = 1; } return a; }
|
JavaScript 1.6 / ECMAScript 5 的数组有一个原生的方法filter,速度也非常快,
也可以达到uniq的效果:
1 2 3 4 5 6 7
| function onlyUnique(value, index, self) { return self.indexOf(value) === index; } var a = ['a', 1, 'a', 2, '1']; var unique = a.filter( onlyUnique );
|
另外jQuery竟然有grep方法,而且速度出乎意料的快:
1 2 3
| arr = $.grep(arr, function(v, k){ return $.inArray(v ,arr) === k; });
|
表示从来没用过Array自带的reduce方法,用于去重同样令人惊艳:
1 2 3
| [0,1,2,0,3,2,1,5].reduce(function(prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []);
|
有一个小学生人在stackoverflow上号称是比所有算法都要快10倍以上的算法:
1 2 3 4 5 6 7 8
| var array=[1,2,3,4,5,6,7,8,9,0,1,2,1]; function toUnique(a,b,c){ b=a.length; while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1); return a } toUnique(array)
|
不过很可惜,我用chrome的console测试的时候由于计算时间太长,页面crash掉了。
总结:用很奇怪的算法来提升性能有时候确实效果惊人,但是也要注意写好充分封装和注释,
要不然鬼才看得出来你写的算法是干嘛用的(“鬼才”是谁?好厉害!)233~~