I'm trying to work on this problem where we compute Nested weight sum for a given array of numbers.
Given a nested list of integers, return the sum of all integers in the
list weighted by their depth.
For example for:
[[1,1],2,[1,1]] ====> solution is 10.
Four 1's at depth 2, one 2 at depth 1.
Here's the code i wrote:
var depthSum = function (nestedList, sum=0, depth=1) {
for(let i=0; i<nestedList.length; i++){
let val = nestedList[i];
if (Array.isArray(val)) {
return depthSum(val, sum, depth+1);
} else {
sum += val * depth;
}
};
return sum;
};
I'm trying to work on the converse problem. i.e
Given a nested list of integers, return the sum of all integers in the
list weighted by their depth. Where weight is increasing from root to
leaf, now the weight is defined from bottom up. i.e., the leaf level
integers have weight 1, and the root level integers have the largest
weight.
Example:
[[1,1],2,[1,1]] ===> Solution is 8.
How can I use the same approach and solve this problem?
(https://leetcode.com/problems/nested-list-weight-sum-ii/description/)
This should do the job, but I wish I had a premium leetcode account to verify that. The idea is to do a search to find the maximum depth in the structure, then use your previous algorithm but with the depth calculation inverted. Also, doing it without recursion means less chance of timing out and no chance of blowing the stack. I added a few basic test cases, but again, no guarantees.
const search = a => {
let sum = 0;
let depth = 0;
const stack = [[a, 0]];
while (stack.length) {
const curr = stack.pop();
if (curr[1] > depth) {
depth = curr[1];
}
for (const e of curr[0]) {
if (Array.isArray(e)) {
stack.push([e, curr[1] + 1]);
}
}
}
stack.push([a, ++depth]);
while (stack.length) {
const curr = stack.pop();
for (const e of curr[0]) {
if (Array.isArray(e)) {
stack.push([e, curr[1] - 1]);
}
else {
sum += e * curr[1];
}
}
}
return sum;
};
console.log(search([[1,1],2,[1,1]]));
console.log(search([]));
console.log(search([6]));
console.log(search([[[[3]]]]));
console.log(search([[2],1]));
A basic recursive solution alone like your original depthSum probably won't work for the second requirement, because you need to figure out the total depth before you know the multiplier for the items on the top level of the array. One option is to figure out the depth of the deepest array first, and then use something similar to your original depthSum.
You can use reduce (which is the appropriate method to use to convert an object into a single value) and the conditional (ternary) operator to make your code concise and less repetitive:
const depthCheck = (item) => (
Array.isArray(item)
? 1 + Math.max(...item.map(depthCheck))
: 0
);
// verification:
console.log(depthCheck([[1,1],2,[1,1]])); // total depth 2
console.log(depthCheck([[1,1],2,[1,1,[2,2]]])) // total depth 3
console.log(depthCheck([[1,1,[2,[3,3]]],2,[1,1,[2,2]]])) // total depth 4
console.log('-----')
const depthSum = (nestedList, weight=depthCheck(nestedList)) => (
nestedList.reduce((a, val) => a + (
Array.isArray(val)
? depthSum(val, weight - 1)
: val * weight
), 0)
);
console.log(depthSum([[1,1],2,[1,1]])) // (2)*2 + (1+1+1+1)*1
console.log(depthSum([[1,1],2,[1,1,[2,2]]])) // (2)*3 + (1+1+1+1)*2 + (2+2)*1
console.log(depthSum([[1,1,[2,[3,3]]],2,[1,1,[2,2]]])) // (2)*4 + (1+1+1+1)*3 + (2)*2 + (3+3)*1
You can do this without needing two traversals of the nested array, if you store the sums of the elements per depth in an array during the traversal. Afterwards, you know that the length of this array is the maximum depth, and you can multiply the sums by their correct weight.
The traversal can be done using recursion or a stack, as explained in the other answers. Here's an example using recursion:
function weightedSum(array) {
var sums = [], total = 0;
traverse(array, 0);
for (var i in sums)
total += sums[i] * (sums.length - i);
return total;
function traverse(array, depth) {
if (sums[depth] === undefined)
sums[depth] = 0;
for (var i in array) {
if (typeof array[i] === "number")
sums[depth] += array[i];
else traverse(array[i], depth + 1);
}
}
}
console.log(weightedSum([[],[]]));
console.log(weightedSum([[1,1],2,[1,1]]));
console.log(weightedSum([1,[[],2,2],1,[[3,3,[[5]]],[3]],[]]));
May be you can do as follows with a simple recursive reducer.
var weightOfNested = (a,d=1) => a.reduce((w,e) => Array.isArray(e) ? w + weightOfNested(e,d+1)
: w + d*e, 0);
console.log(weightOfNested([[1,1,[3]],2,[1,1]]));
So OK as mentioned in the comment the above code is weighing the deeper elements more. In order to weigh the shallow ones more we need to know the depth of the array in advance. I believe this way or that way you end up traversing the array twice... once for the depth and once for calculating the weighted sum.
var weightOfNested = (a, d = getDepth(a)) => a.reduce((w,e) => Array.isArray(e) ? w + weightOfNested(e,d-1)
: w + d*e, 0),
getDepth = (a, d = 1, t = 1) => a.reduce((r,e) => Array.isArray(e) ? r === t ? getDepth(e,++r,t+1)
: getDepth(e,r,t+1)
: r, d);
console.log(weightOfNested([[1,1,[3]],2,[1,1]])); // depth is 3
Suppose I have the following factors:
(1+3x)(1+x)(1+2x)
Expanded to a polynomial, it looks like:
1 + 6x + 11x^2 + 6x^3
The coefficients of this polynomial would be
c0 = 1
c1 = 6
c2 = 11
c3 = 6
I'm trying to figure out how to calculate these rapidly (for any set of factors). The ideal output would be an array of the coefficients, like
var coeff = [c0,c1,c2,c3];
What I'm trying to do is find a way to quickly go from the factors to the array of coefficients. Any suggestions on how to rapidly handle this in javascript? And for the sake of clarity, I'm trying to figure out how to do this for any set of n factors, not just this particular scenario.
You could use the factors as vector and use a cross product for the result.
function multiply(a1, a2) {
var result = [];
a1.forEach(function (a, i) {
a2.forEach(function (b, j) {
result[i + j] = (result[i + j] || 0) + a * b;
});
});
return result;
}
var data = [[1, 3], [1, 1], [1, 2]], // (1+3x)(1+x)(1+2x)
result = data.reduce(multiply);
console.log(result); // [1, 6, 11, 6] = 1x^0 + 6x^1 + 11x^2 + 6x^3
Well I found a method to do what you want from start to finish even without the need for any treatment in the original factors. Although I had to use a Math library. I found there is at least a library that does what you want: Nerdamer
As you can see from the code below the coeficients are correctly calculated from the factors you gave.
var factors = '(1+3x)(1+x)(1+2x)';
console.log('original factors: ' + factors);
var y = nerdamer('expand(' + factors + ')');
var polynomialform = y.toString();
console.log('polynomial form: ' + polynomialform);
var coef = polynomialform.split('+').map(v=>v.trim()).map(v=>v.split('x')[0]).map(v=>v.replace(/^\*+|\*+$/g, ''));
console.log('coeficients: ' + coef);
<script src="http://nerdamer.com/js/nerdamer.core.js"></script>
Notice that coefs var is an array.
Obviously, by the way I otained the coeficients, the operation may fail in different factor cases. This has to be adapted for minus characters and edge cases. You can create some kind of loop and put failed calculations in an array to check for edge cases to adapt the code for the full dataset. I can improve the answer if you provide a larger test dataset.
Hope it helps you.
Here's my take based on the fact that when you multiply (1+ax) by (1+b_1*x+b_2*x^2+...+b_nx^n), in the resulting polynomial (of degree n+1), the first term's coefficient will be one and its last term's coefficient will be a*b_n.
I think it is a bit simpler than the accepted answer, but still quadratic in time. To make this more efficient, you will need more advanced techniques.
function multOne(a, b) {
var n = b.length;
var r = [1]; //The first term is always 1
r[n] = a * b[n - 1]; //The last term is always a*b_n-1
for (var i = 1; i < n; i++)
r[i] = b[i] + a * b[i - 1];
return r;
}
function solve(c) {
var result = [1, c[0]]; //use result as an accumulator
for (var j = 1; j < c.length; j++)
result = multOne(c[j], result);
return result;
}
console.log(solve([3, 1, 2])); //You don't need to pass 1s either. Just pass the varying coefficients
I needed something similar (to calculate permutations via exponential generating functions) so I wrote a version that works when some terms missing, by using objects as the base instead. I also needed it not not calculate anything over a certain power, so that's also an option
/**
* Calculates the result of multiplying many polynomials together
* #example
* polynomials = [{0: 1, 1: 10, 2:1}, {0: 0, 1: 5, 2: 0, 3: 0.5}]
* limit = 4;
* polynomialMultiplication(polynomials, limit);
* #param {Array.<Object.<number,number>>} polynomials an array of polynomials,
* each expressed as an array of term coefficients
* #param {number} limit the maximum term to calculate
* #returns the resultant polynomial from multiplying all polynomials together
*/
function polynomialMultiplication(polynomials, limit) {
const length = limit ?? polynomials.reduce((sum, poly) => sum += Math.max(...Object.keys(poly)), 0)
// make an object to hold the result in
// which is prepopulated by zeros
const template = { ...Array.from({
length
}).fill(0)
};
return polynomials.reduce((memo, poly, polyIndex) => {
const tempCopy = { ...template};
if (polyIndex === 0) return { ...poly };
for (let termIndex = 0; termIndex < length && termIndex <= Math.max(...Object.keys(poly)); termIndex++) {
for (let memoIndex = 0;
(memoIndex + termIndex) <= length && memoIndex <= Math.max(...Object.keys(memo)); memoIndex++) {
const addition = (memo[memoIndex] ?? 0) * (poly[termIndex] ?? 0);
const copyIndex = memoIndex + termIndex;
tempCopy[copyIndex] = (tempCopy[copyIndex] ?? 0) + addition;
}
}
return tempCopy;
}, template)
}
console.log('(1+3x)(1+x)(1+2x)');
const polynomials = [{
0: 1,
1: 3
}, {
0: 1,
1: 1
}, {
0: 1,
1: 2
}];
console.log(polynomialMultiplication(polynomials));
const morePolynomials = [{
0: 1,
1: 0,
2: 5
}, {
0: 0,
1: 6
}, {
0: 1,
1: 2,
2: 0
}];
console.log('(1+5x^2)(6x)(1+2x) up to x^2')
console.log(polynomialMultiplication(morePolynomials, 2));
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
This question already has answers here:
How to find the sum of an array of numbers
(59 answers)
Closed 3 months ago.
I am having problems adding all the elements of an array as well as averaging them out. How would I do this and implement it with the code I currently have? The elements are supposed to be defined as I have it below.
<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>
A solution I consider more elegant:
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}.`);
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);
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 );
Just iterate through the array, since your values are strings, they have to be converted to an integer first. And average is just the sum of values divided by the number of values.
Calculating average (mean) using reduce and ES6:
const average = list => list.reduce((prev, curr) => prev + curr) / list.length;
const list = [0, 10, 20, 30]
average(list) // 15
Shortest one liner for Average
const avg = arr => arr.reduce((acc,v,i,a)=>(acc+v/a.length),0);
Shortest one liner for Sum
const sum = arr => arr.reduce((a,b)=>a+b);
Let's imagine we have an array of integers like this:
var values = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
The average is obtained with the following formula
A= (1/n)Σxi ( with i = 1 to n ) ... So: x1/n + x2/n + ... + xn/n
We divide the current value by the number of values and add the previous result to the returned value.
The reduce method signature is
reduce(callback[,default_previous_value])
The reduce callback function takes the following parameters:
p : Result
of the previous calculation
c : Current value (from the current index)
i : Current array element's index value
a : The current reduced Array
The second reduce's parameter is the default value ... (Used in case the array is empty ).
So the average reduce method will be:
var avg = values.reduce(function(p,c,i,a){return p + (c/a.length)},0);
If you prefer you can create a separate function
function average(p,c,i,a){return p + (c/a.length)};
function sum(p,c){return p + c)};
And then simply refer to the callback method signature
var avg = values.reduce(average,0);
var sum= values.reduce(sum,0);
Or Augment the Array prototype directly..
Array.prototype.sum = Array.prototype.sum || function (){
return this.reduce(function(p,c){return p+c},0);
};
It's possible to divide the value each time the reduce method is called..
Array.prototype.avg = Array.prototype.avg || function () {
return this.reduce(function(p,c,i,a){return p+(c/a.length)},0);
};
Or even better , using the previously defined Array.protoype.sum()
method, optimize the process my calling the division only once :)
Array.prototype.avg = Array.prototype.avg || function () {
return this.sum()/this.length;
};
Then on any Array object of the scope:
[2, 6].avg();// -> 4
[2, 6].sum();// -> 8
NB: an empty array with return a NaN wish is more correct than 0 in my point of view and can be useful in specific use cases.
generally average using one-liner reduce is like this
elements.reduce(function(sum, a,i,ar) { sum += a; return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);
specifically to question asked
elements.reduce(function(sum, a,i,ar) { sum += parseFloat(a); return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);
an efficient version is like
elements.reduce(function(sum, a) { return sum + a },0)/(elements.length||1);
Understand Javascript Array Reduce in 1 Minute
http://www.airpair.com/javascript/javascript-array-reduce
as gotofritz pointed out seems Array.reduce skips undefined values.
so here is a fix:
(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])
You can also use lodash, _.sum(array) and _.mean(array) in Math part (also have other convenient stuff).
_.sum([4, 2, 8, 6]);
// => 20
_.mean([4, 2, 8, 6]);
// => 5
Not the fastest, but the shortest and in one line is using map() & reduce():
var average = [7,14,21].map(function(x,i,arr){return x/arr.length}).reduce(function(a,b){return a + b})
I use these methods in my personal library:
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);
}
EDIT:
To use them, simply ask the array for its sum or average, like:
[1,2,3].sum() // = 6
[1,2,3].average() // = 2
In ES6-ready browsers this polyfill may be helpful.
Math.sum = (...a) => Array.prototype.reduce.call(a,(a,b) => a+b)
Math.avg = (...a) => Math.sum(...a)/a.length;
You can share same call method between Math.sum,Math.avg and Math.max,such as
var maxOne = Math.max(1,2,3,4) // 4;
you can use Math.sum as
var sumNum = Math.sum(1,2,3,4) // 10
or if you have an array to sum up,you can use
var sumNum = Math.sum.apply(null,[1,2,3,4]) // 10
just like
var maxOne = Math.max.apply(null,[1,2,3,4]) // 4
One sneaky way you could do it although it does require the use of (the much hated) 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/>");
Just thought I'd post this as one of those 'outside the box' options. You never know, the slyness might grant you (or taketh away) a point.
Here is a quick addition to the “Math” object in javascript to add a “average” command to it!!
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;
}
Then i have this addition to the “Math” object for getting the sum!
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;
}
So then all you do is
alert(Math.sum([5,5,5])); //alerts “15”
alert(Math.average([10,0,5])); //alerts “5”
And where i put the placeholder array just pass in your variable (The input if they are numbers can be a string because of it parsing to a number!)
I found Mansilla's answer to work fine with the extension of making sure that I am doing summation of floats and not concatonation of strings using parseFloat():
let sum = ourarray.reduce((a, b) => parseFloat(a) + parseFloat(b), 0);
let avg = (sum / ourarray.length) || 0;
console.log(sum); // print out sum
console.log(avg); // print out avg
set your for loop counter to 0.... you're getting element 9 and then you're done as you have it now. The other answers are basic math. Use a variable to store your sum (need to cast the strings to ints), and divide by your array length.
Start by defining all of the variables we plan on using. You'll note that for the numbers array, I'm using the literal notation of [] as opposed to the constructor method array(). Additionally, I'm using a shorter method to set multiple variables to 0.
var numbers = [], count = sum = avg = 0;
Next I'm populating my empty numbers array with the values 0 through 11. This is to get me to your original starting point. Note how I'm pushing onto the array count++. This pushing the current value of count, and then increments it for the next time around.
while ( count < 12 )
numbers.push( count++ );
Lastly, I'm performing a function "for each" of the numbers in the numbers array. This function will handle one number at a time, which I'm identifying as "n" within the function body.
numbers.forEach(function(n){
sum += n;
avg = sum / numbers.length;
});
In the end, we can output both the sum value, and the avg value to our console in order to see the result:
// Sum: 66, Avg: 5.5
console.log( 'Sum: ' + sum + ', Avg: ' + avg );
See it in action online at http://jsbin.com/unukoj/3/edit
I am just building on Abdennour TOUMI's answer. here are the reasons why:
1.) I agree with Brad, I do not think it is a good idea to extend object that we did not create.
2.) array.length is exactly reliable in javascript, I prefer Array.reduce beacuse a=[1,3];a[1000]=5; , now a.length would return 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;
};
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 ) ;
};
Then :
[ 1 , 2 , 3].avg() ; //-> OUT : 2
[{age:25},{age:26},{age:27}].avg(function(e){return e.age}); // OUT : 26
On evergreen browsers you can use arrow functions
avg = [1,2,3].reduce((a,b) => (a+b);
Running it 100,000 times, the time difference between the for loop approach and reduce is negligible.
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.
*/
If you are in need of the average and can skip the requirement of calculating the sum, you can compute the average with a single call of 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
If anyone ever needs it - Here is a recursive average.
In the context of the original question, you may want to use the recursive average if you allowed the user to insert additional values and, without incurring the cost of visiting each element again, wanted to "update" the existing average.
/**
* 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
How:
this works by maintaining the current average and element count. When a new value is to be included you increment count by 1, scale the existing average by (count-1) / count, and add newValue / count to the average.
Benefits:
you don't sum all the elements, which may result in large number that cannot be stored in a 64-bit float.
you can "update" an existing average if additional values become available.
you can perform a rolling average without knowing the sequence length.
Downsides:
incurs lots more divisions
not infinite - limited to Number.MAX_SAFE_INTEGER items unless you employ BigNumber
Having read the other choices, I will try to make a simpler version for the future viewers, elaborating on the existing code and not creating a more elegant one. First of all, you declared the numbers as strings. Apart from the .parseInt we can also do:
const numberConverter = elmt.map(Number);
So what map does is that it "returns a copy of the original array". But I convert its values to numbers. Then we can use the reduce method (It can also be simpler, but I am writing easy to read versions and I also have 2 average methods) What the reduce method does is it has an accumulator that gets bigger and bigger if you add values to it, as it iterates through the array and adds (in this case) the currentValue to it.:
var i;
const 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';
console.log(elmt);
const numberConverter = elmt.map(Number);
const sum = numberConverter.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
const average = numberConverter.reduce(
(accumulator, currentvalue, index, numArray) => {
return accumulator + currentvalue / numArray.length;
},
0
);
const average2 =
numberConverter.reduce(
(accumulator, currentValue) => accumulator + currentValue,
0
) / numberConverter.length;
for (i = 9; i < 10; i++) {
console.log(
`The sum of all the elements is: ${sum}. <br> The average of all the elements is: ${average2}`
);}
Unless I missed something, every solution up to this point uses the length of the list to calculate the average after summing the values.
There is a downside to this approach that a slightly modified, yet still simple algorithm will address without the downsides.
The downside is that you assuming that there won't be an overflow by summing all the numbers. If you have a lot of numbers that are very big, and you add them all up, they may exceed the maximum size that can fit into the data type.
A better approach is to simply calculate the average as you go, rather than summing it and then dividing with the length at the end:
function getAvg(values) {
return values.reduce((m, x, i) => m + (x - m) / (i + 1), 0)
}
Props to Knuth's "Art of Computer Programming" vol. 2.
just for fun
let avg = [81, 77, -88, 195, 6.8].reduce((a,e,i) => (a*i+e)/(i+1));
console.log(avg)
Just for kicks:
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)));
I think we can do like
var k=elmt.reduce(function(a,b){return parseFloat(a+parseFloat(b));})
var avg=k/elmt.length;
console.log(avg);
I am using parseFloat twice because
when
1) you add (a)9+b("1") number then result will be "91" but we want addition. so i used parseFloat
2)When addition of (a)9+parseFloat("1") happen though result will be "10" but it will be in string which we don't want so again i used parseFloat.
I hope i am clear. Suggestions are welcome
Here is my rookie way of simply finding the avg. Hope this helps somebody.
function numAvg(num){
var total = 0;
for(var i = 0;i < num.length; i++) {
total+=num[i];
}
return total/num.length;
}
here's your one liner:
var average = arr.reduce((sum,item,index,arr)=>index !== arr.length-1?sum+item:sum+item/arr.length,0)
I think this may be a direct solution to calculate the average with a for loop and function.
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);
There seem to be an endless number of solutions for this but I found this to be concise and elegant.
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
Or more consisely:
const numbers = [1,2,3,4];
const average = numbers.map(x => x/numbers.length).reduce((adder, value) => (adder + value));
console.log(average); // 2.5
Depending on your browser you may need to do explicit function calls because arrow functions are not supported:
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
Or:
const average1 = numbers
.map(function (x) {
return x/count;
})
.reduce(function (adder, value) {
return adder + value;
});
console.log(average1);