please don't kill me right away, because some topics are already here in the forum. I've read and tried a lot. I just don't get any further with my beginner knowledge.
My problem is the following: I have 4 arrays, the length of the arrays can have a different length each time. Now I would like to add the sum of all 4 arrays and get a final result.
I just can't really get any further than I want. Please bear with me and help me.
Here my example :
var MyData = '{"M":[{"M":{"MD":995,"PT":1,"TT":17,"D":0,"TID":44,"T":0,"HW":109,"KD":0,"TA":[4,17,77,17010,84,5,6,6,6,5,"xxxx",0,0,128,6,-1,0,34,[],0],"SD":1187,"OD":117,"SA":[1,65,67,194,187,7,8,7,6,6,"yyyy",0,0,-1,-1,-1,0,95,[],0]},"UM":{"PD":0,"TD":0,"L":{"ID":23,"ID":2,"VIS":14,"N":"bbbb","GD":102,"L":17,"W":1429,"D":113,"SPR":9,"Q":[[1647,1,2,5,-1,[[4,40,[114.0]],[5,46,[74.3]],[18,89,[43.6]],[116,34,[42.2]]],-1,-1,0,-1,-1,3,[1,5,3090,[7222,32,5,310,[[312,46,[11.4]],[311,55,[12.8]],[34,72,[19.7]],[30,28,[8.4]]],0]]],[187,2,2,5,-1,[[1,9,[82.4]],[2,86,[86.3]],[112,67,[28.1]],[19,35,[22.0]]],-1,-1,0,-1,-1,3,[2,6,2970,[7127,32,6,3240,[[311,28,[8.5]],[314,67,[18.7]],[32,83,[17.3]],[315,46,[8.0]]],0]]],[14650745,3,2,5,-1,[[3,97,[116.8]],[6,55,[74.8]],[109,42,[24.8]],[116,65,[67.0]]],-1,-1,0,-1,-1,3,[3,6,3590,[77381,32,6,3130,[[313,33,[6.3]],[310,83,[21.1]],[312,61,[13.8]],[311,36,[9.8]]],0]]],[14673,4,2,5,-1,[[7,82,[16.1]],[115,40,[21.0]],[121,87,[215,871.0]],[112,48,[22.4]]],-1,-1,0,-1,-1,3,[4,6,3570,[72077,32,2,2710,[[312,44,[11.0]],[311,52,[12.3]],[313,37,[6.8]],[38,38,[8.8]]],0]]],[14681483230,5,2,0,0,[[21,[5.0]]],1070,-1,0,630006,-1,2],[14649672824,6,2,15,-1,[[808,82,[47.1]],[811,77,[28.1]],[812,50,[20.0]],[815,35,[18.4]],[20018,100,[1.0]],[20016,7,[2060,12.0,2061,12.0,2062,12.0,2063,12.0,2064,12.0,2065,12.0,2066,12.0,2067,12.0,2068,12.0,148,12.0,2069,12.0,149,12.0,2070,12.0,150,12.0,151,12.0,2071,12.0,2072,12.0,2073,12.0,2074,12.0,2075,12.0,2076,12.0,2077,12.0,2078,12.0,2079,12.0,2020,12.0,2021,12.0,2022,12.0,2023,12.0,2024,12.0,2025,12.0,2026,12.0,2027,12.0,2028,12.0,2029,12.0,2030,12.0,2031,12.0,2032,12.0,2033,12.0,2034,12.0,2035,12.0,2036,12.0,2037,12.0,2038,12.0,2039,12.0]]],-1,-1,0,-1,-1,3,[65,6,3440,[]]]],"IDS":[[10021,1023],[10022,1033]],"SIS":[1033,1009,1040,100253],"AE":[[64,[8.0]],[503,[20.0]],[504,[48.0]],[504,[48.0]],[339,[50.0]],[504,[48.0]],[613,[50.0]],[66,[65.0]],[503,[65.0]],[503,[45.0]],[504,[30.0]],[504,[45.0]],[614,[8.0]],[66,[48.0]],[504,[60.0]],[66,[45.0]],[504,[48.0]],[614,[30.0]],[66,[24.0]]]}},"GA":{"L":[[287,30],[216,2224],[215,744],[298,60],[651,76],[650,90],[649,132],[240,50]],"M":[[287,30],[216,2720],[215,3808],[298,60],[651,48],[650,102],[649,125],[648,179],[240,50]],"R":[[287,30],[216,2968],[298,60],[651,76],[650,90],[649,132],[240,50]],"RW":[[215,2358],[216,433]]},"AST":[390,400],"ATT":0,"SM":0}],"O":[{"OID":8344,"DUM":false,"N":"xrr","E":{"BGT":0,"BGC1":14408394,"BGC2":1644825,"SPT":2,"S1":82,"SC1":144394,"S2":82,"SC2":163,"IS":1},"L":7,"LL":50,"H":3195,"AVZ":180,"CF":3911,"HF":16245,"PRE":13,"SUF":23,"TPX":-1,"MP":459,"R":0,"AID":48,"AR":0,"AN":"drum vv","aee":{"CF":237604,"BGT":7,"BGC1":16825,"BGC2":3012,"BGC3":864,"SPT":23,"S1":2,"SC1":30512,"S2":41,"SC2":164825,"S3":0,"SC3":164825},"RPT":0,"AP":[[0,1007,1062,76,1],[0,1170610,1067,757,4],[0,1211752,1056,755,4],[0,100,1059,72,4],[1,163,710,79,12],[2,16771,809,68,12],[3,2052697,772,504,12]],"VP":[],"SA":0,"VF":0,"PF":1,"RRD":0,"TI":-1},{"OD":1187,"DM":false,"N":"xyz","E":{"BGT":1,"BG1":81264,"BG2":5126,"SPT":1,"S1":82,"S1":16425,"S2":82,"S2":164825,"IS":1},"L":7,"LL":90,"H":6738,"AVP":87345,"CF":4591,"HF":5623,"PRE":13,"SUF":27,"TX":1,"P":8828,"R":0,"AD":88,"AR":7,"AN":"DDR ","aee":{"CF":1878,"BT":2,"BC1":14494,"BG2":1894,"BC3":-1,"SPT":0,"S1":-1,"S1":-1,"S2":-1,"SC2":-1,"S3":-1,"SC3":-1},"RPT":0,"AP":[[0,1417194,675,607,1],[0,2086,795,1180,4],[0,3363161,663,603,4],[0,7164676,769,1179,4],[1,489,490,318,12],[2,208,33,71,12],[3,4347,42,108,12],[4,112,818,61,12]],"VP":[],"A":0,"VF":0,"PF":1,"RD":0,"TI":-1,"RP":-1}]}'
var MyArray = JSON.parse(MyData)
MyArray.M[0].GA.L.forEach(element1 => console.log(element1[1]));
MyArray.M[0].GA.M.forEach(element2 => console.log(element2[1]));
MyArray.M[0].GA.R.forEach(element3 => console.log(element3[1]));
MyArray.M[0].GA.RW.forEach(element4 => console.log(element4[1]));
//So I give myself all the values first.
//If I then use the for loop on one of the arrays, I get the output:
let sum = 0;
MyArray.M[0].GA.L.forEach(element1 => {
const MyArray = [element1[1]];
for (let i = 0; i < MyArray.length; i++) {
sum += MyArray[i];
}
console.log(sum);
})
//output: 30,2254,2998,3058,3134,3224,3356,3406
The number 3406 is the End Result, how can I print only the End result.
If there is another method to add all 4 arrays together at once, it would help me even more.
If possible an example for an array and an example for all 4 together please
you have to do three things: consolidate all the arrays, get the sum of all values, then print it
first, consolidate
const allArrs = [
...MyArray.M[0].GA.L,
...MyArray.M[0].GA.M,
...MyArray.M[0].GA.R,
...MyArray.M[0].GA.RW
]
then, the array method that would help the most here is Array.Reduce
const result = allArrs.reduce((accumulator, currentArray) => {
accumulator += currentArray[1]
return accumulator
}, 0)
then log the result!
As others have pointed out, this type of problem is very well suited for using a functional programming approach, where you simplify the problem by morphing it into a series of atomic operations that have no side-effects.
JavaScript does a great job of implementing the core functional programming methods of map(), filter(), and reduce(). For this problem, the only thing you need is reduce().
The code below could be made smaller and more efficient, but it was written to show each individual step.
const data = JSON.parse(rawData);
// subData is now an object whose members are the arrays you care about
const subData = data.M[0].GA;
// turn that into an array of arrays
const myArrays = Object.values(subData);
// now use reduce() to flatten the array of arrays into a single array with just
// the numbers you want to sum
const myNums = myArrays.reduce((acc, val) => acc.concat(val[1]), []);
// finally, reduce() again to sum the values
const sum = myNums.reduce((acc, val) => acc + val, 0);
console.log(sum);
You're on the right track. Simply move console.log(sum) outside of the final }) so it's not inside any loops.
I hope I understand what you are trying to do. You can simplify your code in this way.
function sum(arr) {
return arr.reduce((acc, item) => acc += item[1], 0);
}
const result = sum(MyArray.M[0].GA.L) + sum(MyArray.M[0].GA.M) + sum(MyArray.M[0].GA.R) + sum(MyArray.M[0].GA.RW);
This is a good example of a use for Array.prototype.reduce. The reduce method loops through all the elements of an array, and uses an accumulator to carry a result through the operation.
const someArray = [ /* any number of values */ ]
const sum = someArray.reduce( ( acc, val ) => ( acc + val )
You can take this a step further and write the callback as a function expression, and dump all of your arrays into a BIGGER array, and use reduce on THAT ONE too!
const summation = ( acc, val ) => ( acc + val )
const sumOfSums = ( acc, val ) => ( acc + val.reduce( summation, 0 ) )
const arrayOfArrays= [
MyArray.M[0].GA.L,
MyArray.M[0].GA.M,
MyArray.M[0].GA.R
MyArray.M[0].GA.RW
]
const total = arrayOfArrays.reduce( sumOfSums, 0 )
console.log( `output: ${total}` )
Can someone explain how this is working.
Learning to use Array.reduce()
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];
var initialValue = {}
var reducer = function(tally, vote) {
if (!tally[vote]) {
tally[vote] = 1;
} else {
tally[vote] = tally[vote] + 1;
}
return tally;
}
var result = votes.reduce(reducer, initialValue)
The way how reduce works is pretty similar to map or filter. In this case, the reducer is responsible for reducing the array of objects into one object.
The reducer function iterates through all elements of your array. The function is called with two arguments, tally - result of reducing so far and vote - array element that is currently being processed.
If tally does not have a property named just like the element that is currently being processed/reduced, it adds such a key to the object and sets its value to one. Otherwise (key is present), it's incremented by one.
For more information go here
There's plenty of verbose explanations of reduce here and other places, but I think a simple visual demonstration might help
[1,2,3].reduce(function(a,b) { return a + b }, 0)
// (((0 + 1) + 2) + 3)
// => 6
You can see:
an input list of 3 elements results in 3 computations
the initial value is used in the computation with the first element
the result of one computation is used in the next computation …
… up until the last computation which is the result of reduce
Now as for your code, we're not building a sum of numbers, we're building up an Object that holds the tally count of each string in an array.
There's no point in me explaining what everyone else did, but it's not surprising this might've been confusing for you because no one explained that this is abuse of an Object.
In truth, an Object is actually not the best data structure choice for this reduction. Here, an Object is used to emulate the behaviour of a Map.
We'll set initialValue to a new Map() and you'll see how the reducer uses more descriptive syntax within. Note comments aren't even necessary because the code says everything it needs to.
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza']
var initialValue = new Map()
var reducer = function (tally, vote) {
if (tally.has(vote))
return tally.set(vote, tally.get(vote) + 1)
else
return tally.set(vote, 1)
}
var result = votes.reduce(reducer, initialValue)
console.log(Array.from(result.entries()))
Output
[
[ "tacos", 2 ],
[ "pizza", 3 ],
[ "fries", 1 ],
[ "ice cream", 2 ]
]
just for funs
I can show you that the visual representation of the sum via reduce is correct/accurate by writing a reducer that builds a string instead of actually adding the numbers
var initialValue = 0
var reducer = function(a,b) { return '(' + a + ' + ' + b + ')' }
var result = [1,2,3].reduce(reducer, initialValue)
console.log(result)
// (((0 + 1) + 2) + 3)
This technique might be useful for you when trying to understand/debug your own reducers
Basically Array.prototype.reduce() method applies a function against an accumulator and each value of the array to reduce it to a single value.
In your example the reduced value (the result of a count operation) is assigned as a property of an object called tally which is returned by .reduce();
I comment your with a brief explanation:
// your data in an array
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];
// optional value to use as the first argument to the first call of the callback when using Array.prototype.reduce().
var initialValue = {}
// tally = previousValue and vote = currentValue
var reducer = function(tally, vote) {
// if tally is not assign as a key in tally object, add key and add value of one, (basically count 1 for one element in your votes array)
if (!tally[vote]) {
tally[vote] = 1;
} else {
// otherwise if tally object has already this key, increment its value by one, (basically it counts how many times each item in votes array is present in the array)
tally[vote] = tally[vote] + 1;
}
return tally;
}
var result = votes.reduce(reducer, initialValue);
console.log(result);
Notes: you can actually avoid using of declaring a variable for initialValue and instead using only var result = votes.reduce(reducer, {});
API documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Some more examples and brief explanation:
https://www.airpair.com/javascript/javascript-array-reduce
I inserted some console.log messages in your code and this helped me understand what was going on.
var votes = ['tacos', 'pizza', 'pizza', 'tacos', 'fries', 'ice cream', 'ice cream', 'pizza'];
var initialValue = {}
var reducer = function(tally, vote) {
console.log("tally: ", tally);
console.log("vote: ", vote);
console.log("tally[vote]: ", tally[vote]);
if (!tally[vote]) {
tally[vote] = 1;
} else {
tally[vote] = tally[vote] + 1;
}
return tally;
}
var result = votes.reduce(reducer, initialValue)
console.log("result: " + JSON.stringify(result));
The reduce() method reduces the array to a single value.
The reduce() method executes a provided function for each value of the array (from left-to-right).
The return value of the function is stored in an accumulator (result/total).
You have this given list:
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];
Then you make an Initial List. You can modify this and the function will be applied for both lists.
var initialValue = {}
"reducer" is initialized as a function. The reason that we place the function in "reducer" is so we can call it more easily further on. You can do whatever you want in this function and it will be executed on the list in the upcoming steps
var reducer = function(tally, vote) {
if (!tally[vote]) {
tally[vote] = 1;
} else {
tally[vote] = tally[vote] + 1;
}
return tally;
}
Finally, the result of the function is stored into the variable.
var result = votes.reduce(reducer, initialValue)
Well, let's try to expand the iteration:
When you execute
votes.reduce(reducer, initialValue)
It actually does this:
reducer(initialValue, votes[0]); // step1, return {'tacos': 1}
reducer(returnedValueOfStep1, votes[1]); // step2, return {'tacos': 1, 'pizza': 1}
reducer(returnedValueOfStep2, votes[2]); // step3, return {'tacos': 1, 'pizza': 2}
reducer(returnedValueOfStep3, votes[3]); // step4 ...
reducer(returnedValueOfStep4, votes[4]); // step5 ...
reducer(returnedValueOfStep5, votes[5]); // step6 ...
reducer(returnedValueOfStep6, votes[6]); // step7 ...
reducer(returnedValueOfStep7, votes[7]); // step8 ...
I think it quite clear right now.
And usually, if we do not provide initialValue as the second parameter for reduce, it will take the first element of array as the initialValue, and starts iteration from the second one:
reducer(votes[0], votes[1]); // step1 ...
reducer(returnedValueOfStep1, votes[2]); // step2 ...
...