freeCodeCamp - Use the reduce Method to Analyze Data - Question

freeCodeCamp - Use the reduce Method to Analyze Data - Question
0

#1

Hello, i managed to do it but with some troubles :confused:
Link: https://beta.freecodecamp.org/en/challenges/functional-programming/use-the-reduce-method-to-analyze-data

My question is, why do i have an undefined value in my filteredList variable near the beginning ?
I’m not feeling good with map() reduce() and filter() functions mixed up with objects. It’s pretty hard.

// the global variable
var watchList = [
                 {  
                   "Title": "Inception",
                   "Year": "2010",
                   "Rated": "PG-13",
                   "Released": "16 Jul 2010",
                   "Runtime": "148 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Christopher Nolan",
                   "Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
                   "Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
                   "Language": "English, Japanese, French",
                   "Country": "USA, UK",
                   "Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.8",
                   "imdbVotes": "1,446,708",
                   "imdbID": "tt1375666",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Interstellar",
                   "Year": "2014",
                   "Rated": "PG-13",
                   "Released": "07 Nov 2014",
                   "Runtime": "169 min",
                   "Genre": "Adventure, Drama, Sci-Fi",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan, Christopher Nolan",
                   "Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
                   "Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
                   "Language": "English",
                   "Country": "USA, UK",
                   "Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.6",
                   "imdbVotes": "910,366",
                   "imdbID": "tt0816692",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "The Dark Knight",
                   "Year": "2008",
                   "Rated": "PG-13",
                   "Released": "18 Jul 2008",
                   "Runtime": "152 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
                   "Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
                   "Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
                   "Language": "English, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
                   "Metascore": "82",
                   "imdbRating": "9.0",
                   "imdbVotes": "1,652,832",
                   "imdbID": "tt0468569",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Batman Begins",
                   "Year": "2005",
                   "Rated": "PG-13",
                   "Released": "15 Jun 2005",
                   "Runtime": "140 min",
                   "Genre": "Action, Adventure",
                   "Director": "Christopher Nolan",
                   "Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
                   "Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
                   "Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
                   "Language": "English, Urdu, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
                   "Metascore": "70",
                   "imdbRating": "8.3",
                   "imdbVotes": "972,584",
                   "imdbID": "tt0372784",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "Avatar",
                   "Year": "2009",
                   "Rated": "PG-13",
                   "Released": "18 Dec 2009",
                   "Runtime": "162 min",
                   "Genre": "Action, Adventure, Fantasy",
                   "Director": "James Cameron",
                   "Writer": "James Cameron",
                   "Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
                   "Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
                   "Language": "English, Spanish",
                   "Country": "USA, UK",
                   "Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
                   "Metascore": "83",
                   "imdbRating": "7.9",
                   "imdbVotes": "876,575",
                   "imdbID": "tt0499549",
                   "Type": "movie",
                   "Response": "True"
                }
];

function findAvgMovies( watchList, director ){
    let filteredList = watchList.map( function( obj ){
		if( obj.Director == director ) {
			let rating = obj.imdbRating;
			
			return rating;
		}
    })
	
	//["8.8", "8.6", "9.0", "8.3", undefined]
	filteredList.splice( filteredList.length - 1 );
	
	let valueAvg = filteredList.reduce( function( a, b ) {
		return ( parseFloat( a ) + parseFloat( b ) );
	}) / filteredList.length;
	
	return valueAvg;
};

var averageRating = findAvgMovies( watchList, "Christopher Nolan" ) ;
console.log( averageRating );

#2

If I’m not mistaken it’s because you are using map()—the director of the last movie in the array is James Cameron and not Christopher Nolan, so the last item is undefined because map() always give you an array of the same length as the input.

Give filter() a go (EDIT: the code will be much simpler with it and it’s designed for cases like this). :slight_smile:


#3

Hello, here my new code:

/*
Link: https://beta.freecodecamp.org/en/challenges/functional-programming/use-the-reduce-method-to-analyze-data
*/

// the global variable
var watchList = [
                 {  
                   "Title": "Inception",
                   "Year": "2010",
                   "Rated": "PG-13",
                   "Released": "16 Jul 2010",
                   "Runtime": "148 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Christopher Nolan",
                   "Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
                   "Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
                   "Language": "English, Japanese, French",
                   "Country": "USA, UK",
                   "Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.8",
                   "imdbVotes": "1,446,708",
                   "imdbID": "tt1375666",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Interstellar",
                   "Year": "2014",
                   "Rated": "PG-13",
                   "Released": "07 Nov 2014",
                   "Runtime": "169 min",
                   "Genre": "Adventure, Drama, Sci-Fi",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan, Christopher Nolan",
                   "Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
                   "Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
                   "Language": "English",
                   "Country": "USA, UK",
                   "Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.6",
                   "imdbVotes": "910,366",
                   "imdbID": "tt0816692",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "The Dark Knight",
                   "Year": "2008",
                   "Rated": "PG-13",
                   "Released": "18 Jul 2008",
                   "Runtime": "152 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
                   "Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
                   "Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
                   "Language": "English, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
                   "Metascore": "82",
                   "imdbRating": "9.0",
                   "imdbVotes": "1,652,832",
                   "imdbID": "tt0468569",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Batman Begins",
                   "Year": "2005",
                   "Rated": "PG-13",
                   "Released": "15 Jun 2005",
                   "Runtime": "140 min",
                   "Genre": "Action, Adventure",
                   "Director": "Christopher Nolan",
                   "Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
                   "Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
                   "Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
                   "Language": "English, Urdu, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
                   "Metascore": "70",
                   "imdbRating": "8.3",
                   "imdbVotes": "972,584",
                   "imdbID": "tt0372784",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "Avatar",
                   "Year": "2009",
                   "Rated": "PG-13",
                   "Released": "18 Dec 2009",
                   "Runtime": "162 min",
                   "Genre": "Action, Adventure, Fantasy",
                   "Director": "James Cameron",
                   "Writer": "James Cameron",
                   "Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
                   "Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
                   "Language": "English, Spanish",
                   "Country": "USA, UK",
                   "Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
                   "Metascore": "83",
                   "imdbRating": "7.9",
                   "imdbVotes": "876,575",
                   "imdbID": "tt0499549",
                   "Type": "movie",
                   "Response": "True"
                }
];

function myDirectors( obj ) {
	if( obj.Director == "Christopher Nolan" ) {
		return true;
	}
};

function findAvgMovies( watchList, director ){
	let directorList = watchList.filter( myDirectors );
	
	//["8.8", "8.6", "9.0", "8.3"]
    let ratingList = directorList.map( function( obj ){
		if( obj.Director == director ) {
			let rating = obj.imdbRating;
			
			return rating;
		}
    });
	
	let valueAvg = ratingList.reduce( function( a, b ) {
		return ( parseFloat( a ) + parseFloat( b ) );
	}) / ratingList.length;
	
	return valueAvg;
};

var averageRating = findAvgMovies( watchList, "Christopher Nolan" ) ;
console.log( averageRating );

But i need help with myDirectors function. I can’t make the variable “director” global so i can use it in my “myDirectors()”


#4

You only need one reduce statement to solve this problem. You do not need filter or map. To solve this problem, you only need two pieces of information:

  1. Sum of all the ratings of movies directed by Christopher Nolan
  2. Number of movies directed by Christopher Nolan

With these two pieces of information, you can calculate the average rating for movies directed by Christopher Nolan.


#5

You could do the following with your existing solution to pass in the director argument of your findAvgMovies function:

let directorList = watchList.filter(myDirectors(director) );

and then your myDirectors function would need to look like (removing the unnecessary if statement):

function myDirectors( director ) {
  return function(obj) {
    return obj.Director === director; // returns true for matches without if statement
  };
}

or super simplified using arrow function syntax:

const myDirectors = director => obj => obj.Director === director;

#6

Thanks you. It’s working.
But i’m not sure to understand clearly the “return function(obj) {…};” code. You got back the director variable in the parameter. But now the obj is missing. But you managed to have it back like this… It’s a way to grabe back the “watchList” variable object. But like this… if you could explain a bit.

For the “only reduce()” stuff, i will continue to try out… i already “lost” like 20mn and managed to do nothing with it.
I’m using this from freeCodeCamp https://medium.freecodecamp.org/reduce-f47a7da511a9
if you do have some very usefull stuff to help me to figure it out how to use .reduce() on object and undestand how it performe. Some thing i have trouble to understand is the PRECISE role of what variables in reduce parameter do.
For instance in a simple forloop, i know each value the variables contains but i know how it work. But not really, or at all, for the variable in these types of fonctions like reduce(), map() …

edit: and last, who are you ? you helped me every time i asked :slight_smile:


#7

In the line:

let directorList = watchList.filter(myDirectors(director) );

the myDirectors(director) part is just executing the myDirectors function with the value of director (“Christopher Nolan”) passed into it.

filter expects a callback function, so inside the myDirectors function, I used:

  return function(obj) {
    return obj.Director === director; // returns true for matches without if statement
  };

In the above, I return a function with one argument, which will later be the first argument of the filter callback function representing each item in the watchList array.

Instead of creating the stand alone myDirectors function, you could have done the following inside your findAvgMovies function:

  let directorList = watchList.filter(function(obj) {
    return obj.Director === director; // returns true for matches without if statement
  });

You will notice the function looks identical to the function returned in the modified myDirectors function I created for you.


I suggest studying the documentation for each filter, map, and reduce and working through the examples given in the documentation. All you have to remember is each of these “higher order” functions has a callback function with arguments which contain specific values depending on which arguments are specified in the callback function. For example, the filter callback has 3 arguments (1st argument represents the current item in the iteration, 2nd argument represents the index of the current item in the array, 3rd argument is the actual full array being iterated over). You can name the arguments whatever you want, but it is recommended to give them meaningful names to make your code more readable.

So, if I have had the following array of numbers representing ratings:

var ratingsArr = [8, 10, 9, 7, 6];

and I wanted to create a new array containing only numbers in the ratingsArr which are greater than 8, then I could write:

var ratingsGreaterThanEight = ratingsArr.filter(function(rating) {
  return rating > 8; // only captures numbers where rating > 8  evaluates to true;
});
// ratingsGreaterThanEight will be [10, 9] after the above executes

Now if I wanted to create a new array containing only numbers in the ratingsArr which have an even index, then I would need to add a second argument to the filter callback function (I call it index here):

var ratingsArr = [8, 10, 9, 7, 6];

var ratingsGreaterThanEight = ratingsArr.filter(function(rating,index) {
  return index % 2 === 0; // only captures numbers where the index is even;
});

console.log(ratingsGreaterThanEight)
// displays [8, 9, 6] because 8's index is 0, 9's index is 2, and 6's index is 4

#8

Ok thanks you very much for the time spend helping me. I will give a look at it tomorrow :slight_smile:
Have a good day/night.


#9

Hello, i will try to see the documentation but i still don’t understand the role of the “index”:

var euros = [29.76, 41.85, 46.5]; 

var sum = euros.reduce( function( value, index, euros ){
	return value + index;
	// return value + index;
});

console.log( sum ); //118.11
/*
value:  8   10   9   7   6
index:  0    1   2   4   5
euros:[29.76, 41.85, 46.5]
*/

Because it’s like:
total += 8+0;
total += 10+1
total += 9+2;
total += 7+4;
total += 6+5;

But i’m sure it’s false and it doesn’t make sens.


#10

Actually, reduce has 4 callback function arguments and not 3. The first argument is the accumulator and contains the accumulated value previously returned in the last iteration of the callback. The second argument represents each item in the array being iterated. The third argument represents the index of each item in the array being iterated and the fourth argument represents the entire array being iterated by the reduce function.

Note: reduce also makes use of an optional 2nd parameter known as the initial value for the accumulator to start. If not specified, the first item in the array is used for the starting value of the accumulator and the iteration over the array would start at the 2nd item in the array.

See below for my ratingsArr array example:

var ratingsArr = [8, 10, 9, 7, 6];

var sum = ratingsArr.reduce( function( currentSum, value, index, arr ){
  return currentSum + value;
});

console.log( sum ); // 40

// See iterations below
// 1st iteration - currentSum = 8, value = 10
// 2nd iteration - currentSum = 18, value = 9
// 3rd iteration - currentSum = 27, value = 7
// 4th iteration - currentSum = 34, value = 6
// final value of currentSum = 40

Now if I wanted to start the accumulator argument (currentSum) other than the value of the first item in the array, I would do:

var ratingsArr = [8, 10, 9, 7, 6];

var sum = ratingsArr.reduce( function( currentSum, value, index, arr ){
  return currentSum + value;
}, 1000); // note the use of comma and then a number which represents the initial value of accumulator

console.log( sum ); // 1040

// See iterations below
// 1st iteration - currentSum = 1000, value = 8
// 2nd iteration - currentSum = 1008, value = 10
// 3rd iteration - currentSum = 1018, value =9
// 4th iteration - currentSum = 1027, value = 7
// 5th iteration - currentSum = 1034, value = 6
// final value of currentSum = 1040

What if I just wanted to sum the indexes of ratingsArr? Now you will see how index is used with the reduce function.

var ratingsArr = [8, 10, 9, 7, 6];

var sum = ratingsArr.reduce( function( currentSum, value, index, arr ){
  return currentSum + index; // note the use of index instead of value
}, 0); // note the use of 0 as the initial value of accumulator

console.log( sum ); // 10

// See iterations below
// 1st iteration - currentSum = 0, index = 0
// 2nd iteration - currentSum = 0, index = 1
// 3rd iteration - currentSum = 1, index = 2
// 4th iteration - currentSum = 3, index = 3
// 5th iteration  - currentSum = 6, index = 4
// final value of currentSum = 10

#11

Try this

var averageRating = watchList.filter(elem => elem["Director"] === "Christopher Nolan").reduce((total,elem,index,arr)=>{
  return total+Number(elem["imdbRating"])/arr.length;
},0);

#12

I ran your code successfully,
however I am confused why it works…


var averageRating = 
  watchList
    .filter(elem => elem.Director === "Christopher Nolan")
    .reduce((total,elem,index,arr) => {
      //console.log(total, elem.imdbRating, total + Number(elem.imdbRating) /arr.length);
      return total + Number(elem.imdbRating) /arr.length;
},0);


The console.log statement above outputs:

> 0 "8.8" 2.2 
> 2.2 "8.6" 4.35 
> 4.35 "9.0" 6.6  
> 6.6 "8.3" 8.675  //8.675 is the correct answer

However, i assumed the output would look like this

> 0 "8.8" 2.2 // (0 + 8.8)/4 = 2.2
> 2.2 "8.6" 2.7  // (2.2 + 8.6)/4 = 2.7
> 2.7 "9.0" 2.925 // (2.7 + 9.0)/4 = 2.925
> 2.925 "8.3"  2.80625  // (2.925 + 8.3)/4 = 2.80625

What appears to be happening is that the previous divisions are disregarded in the accumulator:

> 0 "8.8" 2.2 //(8.8)/4 = 2.2
> 2.2 "8.6" 4.35 //(8.8+8.6)/4 = 4.35
> 4.35 "9.0" 6.6  //(8.8+8.6+9.0)/4 = 6.6
> 6.6 "8.3" 8.675 //(8.8+8.6+9.0+8.3)/4 = 8.675

Why is this happening?


#13

In this line division is first performed. Then the result of division increase accumulator (total).

If you change the order of operations like this (making addition first) :

console.log(total, elem.imdbRating, (total + Number(elem.imdbRating)) /arr.length);
return (total + Number(elem.imdbRating)) / arr.length

You got your expected output:


#14

Well, I tried to solve this problem just using reduce() - as randelldawson suggested. Here is my solution. What do you think of it? Could have been anyway better? Thank you!

// the global variable
var watchList = [
                 {  
                   "Title": "Inception",
                   "Year": "2010",
                   "Rated": "PG-13",
                   "Released": "16 Jul 2010",
                   "Runtime": "148 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Christopher Nolan",
                   "Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
                   "Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
                   "Language": "English, Japanese, French",
                   "Country": "USA, UK",
                   "Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.8",
                   "imdbVotes": "1,446,708",
                   "imdbID": "tt1375666",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Interstellar",
                   "Year": "2014",
                   "Rated": "PG-13",
                   "Released": "07 Nov 2014",
                   "Runtime": "169 min",
                   "Genre": "Adventure, Drama, Sci-Fi",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan, Christopher Nolan",
                   "Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
                   "Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
                   "Language": "English",
                   "Country": "USA, UK",
                   "Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
                   "Metascore": "74",
                   "imdbRating": "8.6",
                   "imdbVotes": "910,366",
                   "imdbID": "tt0816692",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "The Dark Knight",
                   "Year": "2008",
                   "Rated": "PG-13",
                   "Released": "18 Jul 2008",
                   "Runtime": "152 min",
                   "Genre": "Action, Adventure, Crime",
                   "Director": "Christopher Nolan",
                   "Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
                   "Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
                   "Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
                   "Language": "English, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
                   "Metascore": "82",
                   "imdbRating": "9.0",
                   "imdbVotes": "1,652,832",
                   "imdbID": "tt0468569",
                   "Type": "movie",
                   "Response": "True"
                },
                {  
                   "Title": "Batman Begins",
                   "Year": "2005",
                   "Rated": "PG-13",
                   "Released": "15 Jun 2005",
                   "Runtime": "140 min",
                   "Genre": "Action, Adventure",
                   "Director": "Christopher Nolan",
                   "Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
                   "Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
                   "Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
                   "Language": "English, Urdu, Mandarin",
                   "Country": "USA, UK",
                   "Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
                   "Metascore": "70",
                   "imdbRating": "8.3",
                   "imdbVotes": "972,584",
                   "imdbID": "tt0372784",
                   "Type": "movie",
                   "Response": "True"
                },
                {
                   "Title": "Avatar",
                   "Year": "2009",
                   "Rated": "PG-13",
                   "Released": "18 Dec 2009",
                   "Runtime": "162 min",
                   "Genre": "Action, Adventure, Fantasy",
                   "Director": "James Cameron",
                   "Writer": "James Cameron",
                   "Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
                   "Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
                   "Language": "English, Spanish",
                   "Country": "USA, UK",
                   "Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
                   "Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
                   "Metascore": "83",
                   "imdbRating": "7.9",
                   "imdbVotes": "876,575",
                   "imdbID": "tt0499549",
                   "Type": "movie",
                   "Response": "True"
                }
];

// Add your code below this line

let averageRating;

function average(director) {
  let count = 0;
  return (sum, film, index, arr) => {
    if (film.Director === director) {
      count ++;
      return sum + Number(film.imdbRating);
    }
    if (index === arr.length -1) {
      return sum / count;
    }
    return sum;
  }
}

averageRating = watchList.reduce(average("Christopher Nolan"), 0);
// Add your code above this line

console.log(averageRating); 

#15

My solution looks like this:

var count = 0;
var averageRating = watchList.reduce((acc, curr) => {
if (curr[“Director”] === “Christopher Nolan”) {
acc += Number(curr[“imdbRating”]);
count++;
}
return acc;

}, 0) / count;

I don’t see why I should use filter() or map(). It passed the test.


#16

Your code has been blurred out to avoid spoiling a full working solution for other campers who may not yet want to see a complete solution. In the future, if you post a full passing solution to a challenge and have questions about it, please surround it with [spoiler] and [/spoiler] tags on the line above and below your solution code.

@Videiraft Congratulations on figuring out to solve the challenge with one reduce statement. Mine is similar to yours. I wanted to solve it without any extra variables and only used the initial value of the reduce as an object to accomplish that.

const averageRating = watchList.reduce((calcObj, movie, idx, arr) =>  {
  if (movie.Director == "Christopher Nolan") {
    calcObj.count++;
    calcObj. sum += Number(movie.imdbRating);
  }
  return idx === arr.length -1 ? calcObj.sum / calcObj.count : calcObj;
},{sum:0, count:0});

#17

I did not know I could blurred it out until I posted it (I saw it in one of your posts). I will try to keep it in mind. I myself hate finding a full solution when I am actually looking for a hint


#18

This is because of order of operations. Multiplication and division always come before addition and substraction.

So…

// incorrrect order grouping
 "8.8" 2.2 // (0 + 8.8) / 4 = 2.2

// correct grouping
 "8.8" 2.2 // 0 + (8.8 / 4) = 2.2

#19

hi there! very neat solve! :+1:
could you, please, explain why checking for the end of the watchList array, and returning the accumulator Obj if it’s not the end, is essential for the solution to work?

I’ve written a very similar almost-solution, but I was passing only 2 args (an accumulator and the current value) to reduce() and it was spitting out a NaN. ;/


#21

Once you reach the end of the array, you know that all objects/movies have been checked and summed accordingly, so you know you should perform and return the average based on the ratings sum and ratings count. On the iterations where the director is not Christopher Nolan, you just want to return the calcObj, because you need it in the next iteration in case a movie is directed by Christopher Nolan (to increase the sum and count properties of calcObj).