最快的JavaScript总结

时间:2010-09-21 16:54:42

标签: javascript arrays function

在JavaScript中总结数组的最快方法是什么?快速搜索会翻转a few different methods,但如果可能的话,我想要一个原生解决方案。这将在SpiderMonkey下运行。

在我一直在使用的方式内思考:

var count = 0;
for(var i = 0; i < array.length; i++)
{
    count = count + array[i];
}

我确信有更好的方法然后直接迭代。

10 个答案:

答案 0 :(得分:119)

您应该可以使用reduce

var sum = array.reduce(function(pv, cv) { return pv + cv; }, 0);

Source

在ES6中引入arrow functions,它甚至更简单:

sum = array.reduce((pv, cv) => pv + cv, 0);

答案 1 :(得分:30)

的改进


您的循环结构可以更快:


   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];
   }

这相当于一段时间的反向循环。它缓存该值并与0进行比较,从而加快迭代速度。

要获得更完整的比较列表,请参阅我的 JSFiddle 注意: array.reduce在那里很糟糕,但在Firebug Console中它是最快的。


比较结构

我开始使用 JSPerf 进行数组求和。它很快被构建,并不能保证完整或准确,但这就是编辑用于:)

答案 2 :(得分:20)

在搜索对数组求和的最佳方法时,我编写了一个性能测试。

在Chrome中,“减少”似乎非常优越

我希望这会有所帮助

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

eval:5233.000ms

循环:255.000ms

减少:70.000ms

while:214.000ms

答案 3 :(得分:5)

根据this test,最快的循环是反向循环

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为数组类添加了一个sum方法......你可以轻松地将它作为辅助函数。

答案 4 :(得分:3)

或者你可以用邪恶的方式做到这一点。

var a = [1,2,3,4,5,6,7,8,9];

sum = eval(a.join("+"));

答案 5 :(得分:2)

针对您的具体情况,只需使用数组的reduce方法:

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

答案 6 :(得分:1)

基于this test (for-vs-forEach-vs-reduce)this (loops)

我可以这样说:

1 #Fastest:for loop

var total = 0;

for (var i = 0, n = array.length; i < n; ++i)
{
    total += array[i];
}

2#Aggregate

对于你的情况你不需要这个,但它增加了很多灵活性。

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

不确定的方法

然后forEachreduce具有几乎相同的性能,并且因浏览器而异,但无论如何它们的性能最差。

答案 7 :(得分:0)

最简单,最快速,更可重复和最灵活的一个是:

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()

答案 8 :(得分:0)

两个末端相加怎么办?这样可以将时间缩短一半。像这样:

1,2,3,4,5,6,7,8;总和= 0

2、3、4、5、6、7;总和= 10

3,4,5,6;总和= 19

4,5;总和= 28

sum = 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()在浏览器中对其进行测试时,它的执行速度更快。 我认为这是一种更好的方法。你们怎么看?

答案 9 :(得分:0)

我尝试使用performance.now()分析不同类型的循环的性能。我采用了一个非常大的数组,并发现了数组中所有元素的总和。我每次都运行了三次代码,发现 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"

//做一会儿

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"

//反向循环

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"