如何计算数组中元素的总和和平均值?


177

我在添加数组的所有元素以及将它们取平均值时遇到了问题。我该怎么做,并用我现在拥有的代码实现它?这些元素应该定义如下。

<script type="text/javascript">
//<![CDATA[

var i;
var elmt = new Array();

elmt[0] = "0";
elmt[1] = "1";
elmt[2] = "2";
elmt[3] = "3";
elmt[4] = "4";
elmt[5] = "7";
elmt[6] = "8";
elmt[7] = "9";
elmt[8] = "10";
elmt[9] = "11";

// Problem here
for (i = 9; i < 10; i++){
  document.write("The sum of all the elements is: " + /* Problem here */ + " The average of all the elements is: " + /* Problem here */ + "<br/>");
}   

//]]>
</script>

26
var elmt = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]会好得多。
James McLaughlin

Answers:


134
var sum = 0;
for( var i = 0; i < elmt.length; i++ ){
    sum += parseInt( elmt[i], 10 ); //don't forget to add the base
}

var avg = sum/elmt.length;

document.write( "The sum of all the elements is: " + sum + " The average is: " + avg );

只需遍历数组,由于您的值是字符串,因此必须先将它们转换为整数。平均值就是值的总和除以值的数量。


13
我唯一要做的改进是替换for(var i = 0; i < elmt.length; i++;)for(var i = 0, l = elmt.length; i < l; i++)
Dan D.

5
不要成为那个家伙或不在话题上,但是将基数参数包含在parseInt()中是一个好习惯。我的意思是sum += parseInt(elmt[i], 10);假设ELMT [i]是在底座10的链路
莱德布鲁克斯

9
当心被0除(elmt.length可能是0)
caulitomaz

2
@BramVanroy短篇小说:不,它不会每次都设置“ l”。长话短说:DanD的解决方案是提高性能/速度,因为每一次迭代检查数组的长度要比将长度实际存储在局部变量中并在每次迭代中引用它的速度慢。
CatalinBerta,2015年

9
@VitoGentile和DanD最好不要使用代码来提高性能,而现代浏览器无论如何都将这些代码编译掉。
瑙蒂

496

我认为更优雅的解决方案:

const sum = times.reduce((a, b) => a + b, 0);
const avg = (sum / times.length) || 0;

console.log(`The sum is: ${sum}. The average is: ${avg}.`);

1
这在<= IE8上将不起作用,因为它不支持Array.prototype.reduce()在developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…上
2014年

14
使用累积移动平均线,您可以在reduce函数内完成所有操作(无需执行此sum/times.length步骤):var avg = times.reduce(function(p,c,i){return p+(c-p)/(i+1)},0);
zamnuts 2014年

6
@zamnuts我和你在一起,我认为Thor84no评论完全乱七八糟-我很高兴被发现array.reduce太复杂的地方开除。但是,我也不会使用您的代码,因为事实很简单,它一步步有一个除法和两个额外的加法,而最后却永远不会像单个除法那样高效
gotofritz '16

12
在ES2015中,它要优雅得多。times.reduce((a,b) => (a+b)) / times.length;
Ray Foss

12
@furf 5年后,在许多现代浏览器中,看起来越优雅的“ reduce()”更快(或一样快)。在Chrome 65中,大多数Firefox还原在该测试上效果更好。
罗伯特爵士

116

ES6

const average = arr => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
    
const result = average( [ 4, 4, 5, 6, 6 ] ); // 5
    
console.log(result);


3
改进:Array.prototype.average = function () { var sum = 0, j = 0; for (var i = 0; i < this.length, isFinite(this[i]); i++) { sum += parseFloat(this[i]); ++j; } return j ? sum / j : 0; };
Gilad Peleg 2013年

42
请不要扩展您的代码未创建的对象。
Brad

1
UPDATE不适用于:[“ RER”,“ 4”,“ 3re”,5,new Object()]。average(); 返回0而不是预期的4.5
Luckylooke 2014年

4
当没有长度时,这会特别崩溃
Jimmy Kane

2
@JimmyKane不,它将返回NaN
bzeaman


20

一般平均使用一线减少就是这样

elements.reduce(function(sum, a,i,ar) { sum += a;  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

专门问问题

elements.reduce(function(sum, a,i,ar) { sum += parseFloat(a);  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

一个高效的版本就像

elements.reduce(function(sum, a) { return sum + a },0)/(elements.length||1);

在1分钟内了解Javascript数组精简 http://www.airpair.com/javascript/javascript-array-reduce

正如gotofritz指出的那样,Array.reduce会跳过未定义的值。所以这里是一个解决方法:

(function average(arr){var finalstate=arr.reduce(function(state,a) { state.sum+=a;state.count+=1; return state },{sum:0,count:0}); return finalstate.sum/finalstate.count})([2,,,6])

2
elements.length!=0?elements.length:1 也可以这样写: elements.length || 1 它更短,更容易阅读。
4rzael

2
请记住,这仅适用于没有空白的数组
gotofritz '16

1
建议:添加代码片段的最小版本(实际上只是打印精美),以便人们可以阅读它们。我会自己编辑它们,但是我不喜欢改变人们的答案。
贾斯汀·摩根

16

假设我们有一个像这样的整数数组:

var values = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

通过以下公式获得平均值

A =(1 / n)Σxi (i = 1至n) ...所以:x1 / n + x2 / n + ... + xn / n

我们将当前值除以值数,然后将先前的结果添加到返回的值中。

reduce方法的签名是

reduce(callback[,default_previous_value])

reduce回调函数采用以下参数:

  • p:先前计算的结果
  • c:当前值(来自当前索引)
  • i:当前数组元素的索引值
  • a:电流减少的数组

第二个reduce的参数是默认值 ...(在数组为空的情况下使用)。

因此,平均减少方法将为:

var avg = values.reduce(function(p,c,i,a){return p + (c/a.length)},0);

如果您愿意,可以创建一个单独的功能

function average(p,c,i,a){return p + (c/a.length)};
function sum(p,c){return p + c)};

然后只需参考回调方法签名

var avg = values.reduce(average,0);
var sum= values.reduce(sum,0);

或直接增强Array原型。

Array.prototype.sum = Array.prototype.sum || function (){
  return this.reduce(function(p,c){return p+c},0);
};

每次调用reduce方法都可以对值进行除法。

Array.prototype.avg = Array.prototype.avg || function () {
  return this.reduce(function(p,c,i,a){return p+(c/a.length)},0);
};

或者甚至更好,使用预先定义的 Array.protoype.sum()

方法,我只调用一次优化过程:)

Array.prototype.avg = Array.prototype.avg || function () {
  return this.sum()/this.length; 
};

然后在范围的任何Array对象上:

[2, 6].avg();// -> 4
[2, 6].sum();// -> 8

注意:在我看来,返回NaN愿望的空数组比0更正确,并且在特定用例中很有用。


13

您还可以在Math部分中使用lodash,_.sum(array)和_.mean(array)(也有其他方便的东西)。

_.sum([4, 2, 8, 6]);
// => 20
_.mean([4, 2, 8, 6]);
// => 5

6

不是最快的,而是最短的一行在使用map()和reduce():

var average = [7,14,21].map(function(x,i,arr){return x/arr.length}).reduce(function(a,b){return a + b})

1
也许更短,[7,14,21].reduce((avg,e,i,arr)=>avg+e/arr.length,0);但是对空数组的行为却有所不同。如果您确实希望结果在空数组上为空:[].reduce((a,e,i,arr)=>(a?a:0)+e/arr.length,"")
Valen

自从ES5(于2009年标准化)以来,@ Tobiq map和reduce是非常标准的
Johann Echavarria

for (var avg = 0, length = i = arr.length; i--;) avg += arr[i] / length更清晰,更短,更快
-Tobiq

2
@Tobiq,您的代码不清楚。乍一看,这种类型的循环是难以理解的。
Porkopek '18年

5

尽管确实需要使用(令人讨厌的)eval(),但您可以通过一种偷偷摸摸的方式来实现。

var sum = eval(elmt.join('+')), avg = sum / elmt.length;
document.write("The sum of all the elements is: " + sum + " The average of all the elements is: " + avg + "<br/>");

只是以为我会将其发布为“开箱即用”选项之一。您永远不会知道,狡猾可能会给您(或夺走)一点。


+1高效的单线!如果是客户端浏览器内Javascript,eval()我看到的唯一可能的问题是您需要确保数组仅包含数字(当然,这里的所有其他答案也是如此)。非数字条目会因ReferenceError或崩溃SyntaxError, except nested arrays of numbers which introduce ,导致数字总数不正确。当然,在服务器端JS(例如node.js)中,自然eval()会引入安全性问题。但这对于任何结构良好的客户端使用来说都是完美的。
user56reinstatemonica8 2013年

1
实际上可能存在这样的性能问题eval()-请参阅nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood
user56reinstatemonica8

5

我在个人库中使用以下方法:

Array.prototype.sum = Array.prototype.sum || function() {
  return this.reduce(function(sum, a) { return sum + Number(a) }, 0);
}

Array.prototype.average = Array.prototype.average || function() {
  return this.sum() / (this.length || 1);
}

编辑:要使用它们,只需向数组求和或取平均值即可,例如:

[1,2,3].sum() // = 6
[1,2,3].average() // = 2

整洁的实现,尽管我会实现sum来使用for循环而不是reduce。虽然仍然很干净。
XDS

5

在支持ES6的浏览器中,此polyfill可能会有所帮助。

Math.sum = (...a) => Array.prototype.reduce.call(a,(a,b) => a+b)

Math.avg = (...a) => this.sum(...a)/a.length;

您可以共享相同的呼叫方法之间Math.sumMath.avg 并且Math.max,如

var maxOne = Math.max(1,2,3,4) // 4;

您可以使用Math.sum作为

var sumNum = Math.sum(1,2,3,4) // 10

或者如果您有一个要汇总的数组,则可以使用

var sumNum = Math.sum.apply(null,[1,2,3,4]) // 10

就像

var maxOne = Math.max.apply(null,[1,2,3,4]) // 4

Array.prototype我认为与其添加方法,Math不如将主题添加到对象是更好的选择-它们都是“数字处理程序”。
Oboo Cheng

3

这是对javascript中的“ Math”对象的快速补充,可以向其中添加“ average”命令!

Math.average = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output/input.length;
}

然后,我将这个加到“ Math”对象中以​​求和!

Math.sum = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output;
}

所以你要做的就是

alert(Math.sum([5,5,5])); //alerts “15”
alert(Math.average([10,0,5])); //alerts “5”

我放置占位符数组的位置只是传递了您的变量(如果输入是数字,则输入可以是字符串,因为它可以解析为数字!)


1

将您的for循环计数器设置为0...。您将获得元素9,然后按现在的方式完成操作。其他答案是基本数学。使用变量存储总和(需要将字符串转换为整数),然后除以数组长度。


1

首先定义我们计划使用的所有变量。您会注意到,对于numbers数组,我使用的是文字表示法,[]而不是构造方法array()。此外,我正在使用一种较短的方法将多个变量设置为0。

var numbers = [], count = sum = avg = 0;

接下来,我将数值0到11填充到我的空数字数组中。这是为了让我回到原来的起点。请注意我如何推入阵列count++。这将推动count的当前值,然后在下一次递增。

while ( count < 12 )
    numbers.push( count++ );

最后,我正在为Numbers数组中的数字“执行每个”功能。此函数一次只能处理一个数字,我在函数体内将其标识为“ n”。

numbers.forEach(function(n){
  sum += n; 
  avg = sum / numbers.length;
});

最后,我们可以将sum值和avg值输出到控制台,以查看结果:

// Sum: 66, Avg: 5.5
console.log( 'Sum: ' + sum + ', Avg: ' + avg );

http://jsbin.com/unukoj/3/edit上在线观看它


1

我只是基于Abdennour TOUMI的答案。原因如下:

1.)我同意Brad,我认为扩展我们未创建的对象不是一个好主意。

2.)array.length在javascript中完全可靠,我更喜欢,Array.reduce因为a=[1,3];a[1000]=5;现在a.length返回1001

function getAverage(arry){
    // check if array
    if(!(Object.prototype.toString.call(arry) === '[object Array]')){
        return 0;
    }
    var sum = 0, count = 0; 
    sum = arry.reduce(function(previousValue, currentValue, index, array) {
        if(isFinite(currentValue)){
            count++;
            return previousValue+ parseFloat(currentValue);
        }
        return previousValue;
    }, sum);
    return count ? sum / count : 0; 
};

1
Array.prototype.avg=function(fn){
    fn =fn || function(e,i){return e};
    return (this.map(fn).reduce(function(a,b){return parseFloat(a)+parseFloat(b)},0) / this.length ) ; 
};

然后 :

[ 1 , 2 , 3].avg() ;  //-> OUT : 2

[{age:25},{age:26},{age:27}].avg(function(e){return e.age}); // OUT : 26

1

在常绿浏览器上,您可以使用箭头功能 avg = [1,2,3].reduce((a,b) => (a+b);

运行100,000次,for循环方法与reduce的时间差可以忽略不计。

s=Date.now();for(i=0;i<100000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("100k reduce took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<100000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("100k for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("1M for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("1M reduce took " + (Date.now()-s) + "ms.");

/* 
 * RESULT on Chrome 51
 * 100k reduce took 26ms.
 * 100k for loop took 35ms.
 * 10M for loop took 126ms.
 * 10M reduce took 209ms.
 */


1
您需要详细了解console.timeconsole.timeEnd
Abdennour TOUMI 16-10-4

@AbdennourTOUMI感谢您的提示,我会记住这一点……但是它不是标准的,也不在标准的轨道上。developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd
Ray Foss

1
我知道我正在解决最初的问题,但是如何使用performance.now()进行性能测量?
deejbee

@deejbee确实提供浮点精度...但是它也有点冗长和不兼容。设置标记在现实世界的代码中将很有用
Ray Foss

1

平均最短一线:

let avg = [1,2,3].reduce((a,v,i)=>(a*i+v)/(i+1));

最短一线总和:

let sum = [1,2,3].reduce((a,b)=>a+b);

0

只是为了踢:

var elmt = [0, 1, 2,3, 4, 7, 8, 9, 10, 11], l = elmt.length, i = -1, sum = 0;
for (; ++i < l; sum += elmt[i])
    ;
document.body.appendChild(document.createTextNode('The sum of all the elements is: ' + sum + ' The average of all the elements is: ' + (sum / l)));

0

我认为我们可以做到

var k=elmt.reduce(function(a,b){return parseFloat(a+parseFloat(b));})
var avg=k/elmt.length; 
console.log(avg);

我使用parseFloat两次,因为当1)您添加(a)9 + b(“ 1”)数字时,结果将为“ 91”,但我们要加法。所以我用parseFloat

2)当(a)9 + parseFloat(“ 1”)的加法发生时,尽管结果将是“ 10”,但它将是字符串,我们不希望如此,所以我再次使用parseFloat。

我希望我清楚。欢迎建议


0

这是我的菜鸟简单找到平均值的方法。希望这对某人有帮助。

function numAvg(num){
    var total = 0;
    for(var i = 0;i < num.length; i++) { 
        total+=num[i];
    }
    return total/num.length;
}

0

这是您的一支班轮:

var average = arr.reduce((sum,item,index,arr)=>index !== arr.length-1?sum+item:sum+item/arr.length,0)

0

我认为这可能是使用for循环和函数计算平均值的直接解决方案。

var elmts = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

function average(arr) {
    var total = 0;
    for (var i = 0; i < arr.length; i++) {
        total += arr[i];
    }
        console.log(Math.round(total/arr.length));
}

average(elmts);

0

似乎有无数种解决方案,但是我发现它简洁明了。

const numbers = [1,2,3,4];
const count = numbers.length;
const reducer = (adder, value) => (adder + value);
const average = numbers.map(x => x/count).reduce(reducer);
console.log(average); // 2.5

或更简洁:

const numbers = [1,2,3,4];
const average = numbers.map(x => x/numbers.length).reduce((adder, value) => (adder + value));
console.log(average); // 2.5

取决于您的浏览器,您可能需要执行显式函数调用,因为不支持箭头函数:

const r = function (adder, value) {
        return adder + value;
};
const m = function (x) {
        return x/count;
};
const average = numbers.map(m).reduce(r);
console.log(average); // 2.5

要么:

const average1 = numbers
    .map(function (x) {
        return x/count;
     })
    .reduce(function (adder, value) {
        return adder + value;
});
console.log(average1);

您正在地图功能中进行N个划分。最好先将所有数字都减为一个总值,然后再作一个除法
Eugenio '18

0

如果您需要平均值,并且可以跳过计算总和的要求,则可以通过调用reduce来计算平均值:

// Assumes an array with only values that can be parsed to a Float
var reducer = function(cumulativeAverage, currentValue, currentIndex) {
  // 1. multiply average by currentIndex to find cumulative sum of previous elements
  // 2. add currentValue to get cumulative sum, including current element
  // 3. divide by total number of elements, including current element (zero-based index + 1)
  return (cumulativeAverage * currentIndex + parseFloat(currentValue))/(currentIndex + 1)
}
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce(reducer, 0)); // => 5.5
console.log([].reduce(reducer, 0)); // => 0
console.log([0].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0
console.log([,,,].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0

0

如果有人需要-这是递归平均值。

在原始问题的上下文中,如果允许用户插入其他值,并且不希望再次访问每个元素而要“更新”现有平均值,则可能要使用递归平均值。

/**
 * Computes the recursive average of an indefinite set
 * @param {Iterable<number>} set iterable sequence to average
 * @param {number} initAvg initial average value
 * @param {number} initCount initial average count
 */
function average(set, initAvg, initCount) {
  if (!set || !set[Symbol.iterator])
    throw Error("must pass an iterable sequence");

  let avg = initAvg || 0;
  let avgCnt = initCount || 0;
  for (let x of set) {
    avgCnt += 1;
    avg = avg * ((avgCnt - 1) / avgCnt) + x / avgCnt;
  }
  return avg; // or {avg: avg, count: avgCnt};
}

average([2, 4, 6]);    //returns 4
average([4, 6], 2, 1); //returns 4
average([6], 3, 2);    //returns 4
average({
  *[Symbol.iterator]() {
    yield 2; yield 4; yield 6;
  }
});                    //returns 4

怎么样:

这通过保持当前平均值和元素计数来起作用。当要包含一个新值时,您可以将count递增1,将现有平均值递增(count-1) / count,然后加上newValue / count到平均值中。

优点:

  • 您不能对所有元素求和,这可能导致大量元素无法存储在64位浮点数中。
  • 如果可以使用其他值,则可以“更新”现有平均值。
  • 您可以在不知道序列长度的情况下进行滚动平均。

缺点:

  • 招致更多分裂
  • 不是无限的-限于Number.MAX_SAFE_INTEGER个项目,除非您雇用 BigNumber

-1

HTML内容平均灰度

使用jQuery或Javascript,querySelector您可以直接访问格式化数据...示例:

<p>Elements for an average: <span class="m">2</span>, <span class="m">4</span>,
   <span class="m">2</span>, <span class="m">3</span>.
</p>

因此,有了jQuery,您就有了

var A = $('.m')
  .map(function(idx) { return  parseInt($(this).html()) })
  .get();
var AVG = A.reduce(function(a,b){return a+b}) / A5.length;

查看其他4种方式(!)访问itens并将其平均:http : //jsfiddle.net/4fLWB/


2
拒绝投票是因为OP要求先执行X,然后您告诉他先执行Y,然后再执行X。此外,从DOM中提取数据而不是从数据中创建DOM的想法似乎还是想避免的事情。
eremzeit'1

嗨@eremzeit,谢谢关注。我用粗体的标题说“这是另外一种情况,内容包含在HTML中”,请考虑一下...关于相关性,这种用法(用户直接从HTML看到的数据访问)不是学术性的游戏...它涉及的是“可听取的事实”,即HTML(!)中的内容,而不是JavaScript中的“隐藏于人类中”。不仅在Wikipedia中,还参见典型案例:PMC上有370万篇科学文章网址上有660万份立法文件LexML。有些人不仅使用js设计和玩游戏,还提供审计工具。
彼得·克劳斯

-1

var arr = [1,2,3,4,5]

function avg(arr){
  var sum = 0;
  for (var i = 0; i < arr.length; i++) {
    sum += parseFloat(arr[i])
  }
  return sum / i;
}

avg(arr)====== >>>> 3

这适用于字符串作为数字或数组中的数字。


请对您的答案进行一些解释。
David Hoelzer 2015年

您说对了:将sum定义为数字,这样现在就可以使用了。向函数提供一个数组,它会吐出数组的平均值。
dan chow 2015年

-2
    var scores =[90, 98, 89, 100, 100, 86, 94];
        var sum = 0;
        var avg = 0;
        for(var i = 0; i < scores.length;i++){
  //Taking sum of all the arraylist
            sum = sum + scores[i];   
                }
  //Taking average     
             avg = sum/scores.length;        
  //this is the function to round a decimal no    
             var round = avg.toFixed();
             console.log(round);

1
欢迎使用堆栈溢出。您的答案应详细说明为什么以及如何回答该问题。在鼓励代码段的同时,您应该解释代码,以使访问者可以理解它。这里有一个如何回答的指南:stackoverflow.com/help/how-to-answer
ChrisM

-3

在这种情况下,我会推荐D3。它是最易读的(并提供2种不同的平均值)

let d3 = require('d3');
let array = [1,2,3,4];
let sum = d3.sum(array); //10
let mean = d3.mean(array); //2.5
let median = d3.median(array); 

4
天哪,添加整个D3只是为了计算平均值是荒谬的
gotofritz'April
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.