Reputation: 5254
Say that I've got this array:
testResults = [
{
dateCreated: "2014-07-12",
score: 27.1
},
{
dateCreated: "2014-05-11",
score: 99.3,
},
{
dateCreated: "2014-07-22",
score: 88.8
},
{
dateCreated: "2014-07-01",
score: 33.3
}
];
I want to create a function that:
takes testResults
, startDate
, endDate
, and interval
as arguments and calculates the average test results and returns an array as a result:
calculateTestAverages(testResults, "2014-04-01", "2014-07-30", "month");
would return
testAverages = [0, 99.3, 0, 49.7]
I think for now I want to just create an intermediary 2-D array:
intermediaryArray = [ [0], [99.3], [0], [27.1, 88.8, 33.3] ]
because calculating the average on this intermediary array will be easy.
What I've got so far does NOT work:
// takes a string date and converts it into a Date object.
var convertToDateObject = function(date){
dateObject = new Date(date);
return dateObject;
}
// takes a string date and returns the month.
var getMonth = function(date){
return convertToDateObject(date).getMonth();
}
var calculateTestAverages = function(testResults, startDate, endDate, interval){
var intermediaryArray = [];
if( interval == "month" ){
startingMonth = getMonth(startDate);
endingMonth = getMonth(endDate);
maxArrayIndex = endingMonth - startingMonth;
for (var i = 0; i <= maxArrayIndex; i++){
intermediaryArray[i] = [];
for (var month = startingMonth; month <= endingMonth; month++){
for (var testNumber = 0; testNumber < testResults.length; testNumber++){
if ( getMonth(testResults[testNumber].dateCreated) == month ){
intermediaryArray[i].push(testResults[testNumber].score);
};
};
};
};
};
return intermediaryArray;
}
I've been stuck on this thing for hours. I think my brain is kinda fried at this point.
Upvotes: 1
Views: 171
Reputation: 4847
I will answer your question first and then explain what went wrong. Don't worry about it, the logic behind your code is absolutely fine. It's just a misplaced curly brace i.e. }
.
Let's look at your nested for
loops and see how they proceed:
var intermediaryArray = []; //initialized earlier
...
for (var i = 0; i <= maxArrayIndex; i++){
intermediaryArray[i] = [];
for (var month = startingMonth; month <= endingMonth; month++){
for (var testNumber = 0; testNumber < testResults.length; testNumber++){
if ( getMonth(testResults[testNumber].dateCreated) == month ){
intermediaryArray[i].push(testResults[testNumber].score);
};
};
};
};
In the test case that you provide, length of the intermediaryArray
is 4 which gets calculated perfectly. The outer-most for
loop runs four times. And for every iteration, you do this part:
for (var month = startingMonth; month <= endingMonth; month++){
for (var testNumber = 0; testNumber < testResults.length; testNumber++){
if ( getMonth(testResults[testNumber].dateCreated) == month ){
intermediaryArray[i].push(testResults[testNumber].score);
};
};
};
The code above basically loops from startingMonth
to endingMonth
and finds the appropriate elements of testResulsts
array in that month and is supposed to push it to the intermediaryArray
.
In essence, there should be one entry for a specific month that represents an index
in intermediaryArray
. However, in your for
loop for every index of intermediaryArray
, you do this check against all the months. Let's do a dry run for i = 0
:
i = 0
-----------
startingMonth = 4,
endingMonth = 7
month = 4 : Nothing gets pushed into intermediaryArray[0]
month = 5 : {dateCreated: "05/11/2014",score: 99.3} gets pushed into intermediaryArray[0]
month = 6 : Nothing gets pushed
month = 7 : The remaining 3 tests get pushed into intermediaryArray[0]
Ultimately all the results get pushed into intermediaryArray[0] as we did not change i with the month variable
This is the reason why you in your final returned intermediaryArray
, you had all the testResults
pushed at the end of all the loops.
The workaround is really simple, you initialize the intermediaryArray
once and then populate the intermediaryArray[i]
i.e. push to it new elements every month. In other words, you loop through the intermediaryArray
in the for
loop where you loop through the months because there is a one-one correspondence between the elements.
Something like this would suffice :
for (var i = 0; i <= maxArrayIndex; i++){
intermediaryArray[i] = []; //Initialize the empty array here based on the size
};
for (var month = startingMonth,i=0; month <= endingMonth; month++,i++){
//Simply update the value of i when you update the value of month.
//You don't have to enclose the whole thing into the loop that initialises intermediaryArray
for (var testNumber = 0; testNumber < testResults.length; testNumber++){
if ( getMonth(testResults[testNumber].dateCreated) == month ){
intermediaryArray[i].push(testResults[testNumber].score);
};
};
};
It's good to plan on the constraints that we enforce on for
loops before coding them. Once you know how the arrays are traversed and the way you store it, it's simply about plugging the right conditions into the for
loop. Hope it clarifies things and helps you get started in the right direction.
Upvotes: 2