I’m slowly working my way through this challenge. I’m at the edge of finishing the last stage. My issue is (I think) that I’m not instantiating the accumulator correctly. In my mind, starting at the first number is logical. I add through all the numbers and divide by the length.
This does not work. I feel like I should pick something other than the first number as the instantiated acumulator. Am I right, wrong?
Your code so far
function getRating(watchList) {
let nolan = watchList.filter(film => film.Director === "Christopher Nolan");
let rate = nolan.map(({Title: title, imdbRating: rating})=> ({imdbRating: parseFloat(rating)}));
// Only change code below this line
let averageRating = rate.reduce((acc, cum)=> {acc+cum/rate.length}, rate[0]);
// Only change code above this line
return averageRating;
}
console.log(getRating(watchList));
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
The math doesn’t work right if you use the first number. You need to take the average of all values in the array, so you need the sum of all values divided by the number of values. Your first number is not scaled by the number of values.
Isn’t it also going to use rate[0] twice? It is given as the initial condition, and then the first cum is going to be that same value. You could either give 0 for the initial or give no initial and then it will use the first element as the initial (but then you run into the same problem Jeremy mentioned). Another issue is that I don’t think your callback is returning anything.
Don’t get frustrated. The reduce method is probably the most difficult method for new people to understand. It is actually quite simple and elegant, but until it “clicks” it seems so bizarre. Keep at it, you’ll get it.
Okay. Still working on it. One issue is that the function, when console.logged, returns [object Object][object Object][object Object][object Object]
I don’t know understand how that’s coming back because I (think) I’ve defined everything. My suspicion is that my reduce() function is occluding the data, boxing it in through misuse of variables?
I feel like I’m talking out of my butt here, but that’s the only thing I could come up with.
I also made an empty array as the starter. It’s possible to build off that…but I’m not sure how I should take average. I thought of adding a counter into the reduce() function. It didn’t work on my first go around, but I’m still messing with it. A counter each time reduce goes through a cycle and divide the final sum by that.
Is that feasible?
function getRating(watchList) {
let nolan = watchList.filter(film => film.Director === "Christopher Nolan");
let rate = nolan.map(({Title: title, imdbRating: rating})=> ({imdbRating: parseFloat(rating)}));
console.log(rate)
// Only change code below this line
const averageRating = rate.reduce((ratings, rate)=> {return ratings+=rate}, []);
// Only change code above this line
return averageRating;
}
I solved it. I understand it (I think), but I want to run through what I did.
I will do it below and please clarify or correct my logic where necessary:
Finding the average of movie ratings for Christopher Nolan movies in watchList array object:
[spoiler]
1. Use filter() to squeeze out only movies directed by Christopher Nolan. This is done by using the element `film` to check each key entry of `Director` has the value `'Christopher Nolan'` (TRUE) or not (FALSE).
2. Establish the number of movies by 'Christopher Nolan' using `.length`
3. Use `map()` to structure the data so that it presents only the title of a movie and it's rating AND that the rating is a number and NOT a string. This is done by specifying that the new array produced by `map()` contains the value of `imdbRating` transformed from a string to a number (using `ParseFloat()`)
4. `reduce()` is run on the new array produced by `map()` . The initialized value is 0. `total`is the accumulator. This is increased with each subsequent review rating (indicated by `review`). These are added together and the total sum is returned as `total`.
This total is divided by the sum of Nolan movies in the object and this is the average.
[/spoiler]
Am I understanding what I did correctly? I feel pretty confident, but I want to be sure I’m not misunderstanding something that I did.
function getRating(watchList) {
// Only change code below this line
//filter out Nolan movies
let nolan = watchList.filter(film => film.Director === "Christopher Nolan");
//find amount of Nolan movies
let nolanNum = nolan.length;
//map out title and ratings (with ratings converted into numbers from strings)
let rate = nolan.map(({Title: title, imdbRating: rating})=> ({imdbRating: parseFloat(rating)}));
console.log(rate)
//sum all Nolan ratings together
let nolanSolution = rate.reduce((total, review)=> {total+=review.imdbRating; return total},0);
//average out ratings of Nolan movies
let averageRating = nolanSolution/nolanNum;
// Only change code above this line
return averageRating;
}
If you’re interested in tightening it up a bit, I wonder though, do you need the map? Couldn’t you deal with the numbers in the reduce?
And if you keep the map, why do you need the title? For that matter why do you need to save the elements as objects? Is there something that would make more sense for what we are trying to do?