从非常内部的角度考虑,我一直在使用:
var count = 0;
for(var i = 0; i < array.length; i++)
{
count = count + array[i];
}
我相信有比直接迭代更好的方法。
var count = 0;
for(var i = 0; i < array.length; i++)
{
count = count + array[i];
}
我相信有比直接迭代更好的方法。
reduce
是本地函数,但我对此表示怀疑。在JS的性能优化代码中,尽可能避免函数调用几乎总是更快的。 - MooGoo var count = 0;
for(var i=0, n=array.length; i < n; i++)
{
count += array[i];
}
这样做可以避免在每次迭代中都获取 array.length
,而是缓存了该值。通过缓存值进行优化。
var count=0;
for (var i=array.length; i--;) {
count+=array[i];
}
这相当于一个反向的while循环。它缓存值并与0进行比较,因此迭代速度更快。
有关更完整的比较列表,请参阅我的JSFiddle。
注意:array.reduce在那里表现很差,但在Firebug控制台中是最快的。
我开始了一个用于数组求和的JSPerf。 它是快速构建的,不能保证完整或准确,但这就是编辑的作用 :)
for
循环几乎相同。我进行了测试,有时增量比递减快得多。而且Array.reduce非常慢。http://jsperf.com/array-reduce-vs-foreach/2 - BrunoLMfor (var i = 0, n = array.length; n > i; n--) { sum += array[i]; }
更改为for (var i = 0, n = array.length-1; n >= i; n--) { sum += array[n]; }
。这使其与其他缓存循环大致相同。 - Lukas_Skywalker在寻找数组求和的最佳方法时,我编写了一个性能测试。
在Chrome中,“reduce”似乎要优于其他方法。
希望这有所帮助。
// Performance test, sum of an array
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var result = 0;
// Eval
console.time("eval");
for(var i = 0; i < 10000; i++) eval("result = (" + array.join("+") + ")");
console.timeEnd("eval");
// Loop
console.time("loop");
for(var i = 0; i < 10000; i++){
result = 0;
for(var j = 0; j < array.length; j++){
result += parseInt(array[j]);
}
}
console.timeEnd("loop");
// Reduce
console.time("reduce");
for(var i = 0; i < 10000; i++) result = array.reduce(function(pv, cv) { return pv + parseInt(cv); }, 0);
console.timeEnd("reduce");
// While
console.time("while");
for(var i = 0; i < 10000; i++){
j = array.length;
result = 0;
while(j--) result += array[i];
}
console.timeEnd("while");
评估时间: 5233.000毫秒
循环时间: 255.000毫秒
减少时间: 70.000毫秒
当时间: 214.000毫秒
reduce
函数中需要使用parseInt
?我也尝试了一下,在我的代码中也需要使用它。 - Allen Wang或者你可以用邪恶的方式来做。
var a = [1,2,3,4,5,6,7,8,9];
sum = eval(a.join("+"));
;)
var i = arr.length; while (i--) { }
因此,这段代码可能是您可以获得的最快速度
Array.prototype.sum = function () {
var total = 0;
var i = this.length;
while (i--) {
total += this[i];
}
return total;
}
Array.prototype.sum
为数组类添加了一个求和方法......你也可以将它轻松地变成一个辅助函数。
for(var i=0,n=a.length;i<n;i++){}
。 - vol7ronsum
方法中的 arr
是从哪里来的?arr
真的应该是 this
吗? - Chris Farmerreduce
方法:var sumArray = function() {
// Use one adding function rather than create a new one each
// time sumArray is called
function add(a, b) {
return a + b;
}
return function(arr) {
return arr.reduce(add);
};
}();
alert( sumArray([2, 3, 4]) );
根据这个测试(for-vs-forEach-vs-reduce)和这个(循环),我可以说:
var total = 0;
for (var i = 0, n = array.length; i < n; ++i)
{
total += array[i];
}
对于你的情况来说,你不需要这个功能,但它可以增加很多灵活性。
Array.prototype.Aggregate = function(fn) {
var current
, length = this.length;
if (length == 0) throw "Reduce of empty array with no initial value";
current = this[0];
for (var i = 1; i < length; ++i)
{
current = fn(current, this[i]);
}
return current;
};
使用方法:
var total = array.Aggregate(function(a,b){ return a + b });
接下来是forEach
和reduce
,它们的性能几乎相同并且因浏览器而异,但无论如何它们的性能都是最差的。
// For循环
let arr = [...Array(100000).keys()]
function addUsingForLoop(ar){
let sum = 0;
for(let i = 0; i < ar.length; i++){
sum += ar[i];
}
console.log(`Sum: ${sum}`);
return sum;
}
let t1 = performance.now();
addUsingForLoop(arr);
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 42.17500000959262 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 44.41999999107793 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 49.845000030472875 milliseconds"
// While循环
let arr = [...Array(100000).keys()]
function addUsingWhileLoop(ar){
let sum = 0;
let index = 0;
while (index < ar.length) {
sum += ar[index];
index++;
}
console.log(`Sum: ${sum}`)
return sum;
}
let t1 = performance.now();
addUsingWhileLoop(arr);
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 44.2499999771826 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 44.01999997207895 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 41.71000001952052 milliseconds"
// do-while
let arr = [...Array(100000).keys()]
function addUsingDoWhileLoop(ar){
let sum = 0;
let index = 0;
do {
sum += index;
index++;
} while (index < ar.length);
console.log(`Sum: ${sum}`);
return sum;
}
let t1 = performance.now();
addUsingDoWhileLoop(arr);
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 43.79500000504777 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 43.47500001313165 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 47.535000019706786 milliseconds"
// 反向循环
let arr = [...Array(100000).keys()]
function addUsingReverseLoop(ar){
var sum=0;
for (var i=ar.length; i--;) {
sum+=arr[i];
}
console.log(`Sum: ${sum}`);
return sum;
}
let t1 = performance.now();
addUsingReverseLoop(arr);
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 46.199999982491136 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 44.96500000823289 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 43.880000011995435 milliseconds"
// 反向 while 循环
let arr = [...Array(100000).keys()]
function addUsingReverseWhileLoop(ar){
var sum = 0;
var i = ar.length;
while (i--) {
sum += ar[i];
}
console.log(`Sum: ${sum}`);
return sum;
}
var t1 = performance.now();
addUsingReverseWhileLoop(arr);
var t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 46.26999999163672 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 42.97000000951812 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 44.31500000646338 milliseconds"
// 减少
let arr = [...Array(100000).keys()]
let t1 = performance.now();
sum = arr.reduce((pv, cv) => pv + cv, 0);
console.log(`Sum: ${sum}`)
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 4.654999997001141 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 5.040000018198043 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 4.835000028833747 milliseconds"
// forEach
let arr = [...Array(100000).keys()]
function addUsingForEach(ar){
let sum = 0;
ar.forEach(item => {
sum += item;
})
console.log(`Sum: ${sum}`);
return sum
}
let t1 = performance.now();
addUsingForEach(arr)
let t2 = performance.now();
console.log(`Time Taken ~ ${(t2 - t1)} milliseconds`)
// "Sum: 4999950000"
// "Time Taken ~ 5.315000016707927 milliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 5.869999993592501 mienter code herelliseconds"
// "Sum: 4999950000"
// "Time Taken ~ 5.405000003520399 milliseconds"
其中最简单、最快速、最可重用和灵活的是:
Array.prototype.sum = function () {
for(var total = 0,l=this.length;l--;total+=this[l]); return total;
}
// usage
var array = [1,2,3,4,5,6,7,8,9,10];
array.sum()
那么把两端加起来怎么样?这样可以把时间减半。就像这样:
1、2、3、4、5、6、7、8;总和=0
2、3、4、5、6、7;总和=10
3、4、5、6;总和=19
4、5;总和=28
总和=37
一个算法可能是:
function sum_array(arr){
let sum = 0,
length = arr.length,
half = Math.floor(length/2)
for (i = 0; i < half; i++) {
sum += arr[i] + arr[length - 1 - i]
}
if (length%2){
sum += arr[half]
}
return sum
}
当我使用 performance.now()
在浏览器上测试时,它的性能更快。我认为这是一种更好的方式。你们觉得呢?
O(n/2)
等于O(n)
。为什么?因为你估计的不是给定输入的速度有多快,而是随着输入变化速度如何改变。如果将输入加倍到O(n)函数中,它需要两倍的时间。如果将输入加倍到O(n/2)函数中,它需要两倍的时间。如果将输入加倍到O(n²)中,它需要四倍的时间。 - t.animal