Use reduce method to analyze data help

Can someone help me figure out how to use the reduce function to create the average. I keep getting NaN and dont realise where I am going wrong.

// 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, Elliot 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 getRating(watchList){
  // Only change code below this line

  const filteredList = watchList.filter(movie => movie['Director'] === 'Christopher Nolan')
  const mappedList = filteredList.map(movie => ({Title: movie['Title'], imdbRating: parseFloat(movie['imdbRating']), Director:movie['Director']}))
 const ratings = mappedList.map(ratings => ({rating: ratings['imdbRating']}))
 console.log(ratings)
var averageRating = ratings.reduce((total, rating) => (total + rating) / ratings.length, 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/92.0.4515.159 Safari/537.36 Edg/92.0.902.78

Challenge: Use the reduce Method to Analyze Data

Link to the challenge:

I always say, when in doubt, log it out.

Try this code:

  var averageRating = ratings.reduce((total, rating) => {
    console.log('total', total)
    console.log('rating', rating)
    return (total + rating) / ratings.length, 0
  })

See if that helps you find the problem.

1 Like

I took a look, but still dont understand where I am going wrong. I know the total is the return value but sometimes its showing 0, which I dont get why, and then rating is the current value being processed, not sure if its the initial value of 0 where I am going wrong?

First of all, I screwed up the code a bit, I should have suggested this:

  var averageRating = ratings.reduce((total, rating) => {
    console.log('total', total)
    console.log('rating', rating)
    return (total + rating) / ratings.length
  }, 0)

When I add in that log statement, I see this:

total 0
rating { rating: 8.8 }
total NaN
rating { rating: 8.6 }
total NaN
rating { rating: 9 }
total NaN
rating { rating: 8.3 }

That tells me a few things.

Most of all, ratings is not a number, it looks like an object to me. What are the elements of that array?

So, your formula in that expression on the first pass is:

(0 + { rating: 8.8 }) / { rating: 8.8 }.length

Since that object has no length prop, it is this:

(0 + { rating: 8.8 }) / undefined

That there is your problem.

I also question if your formula is correct, dividing the running total on every pass by the number of elements.

Ratings is an object So you need to get the number from that object. Also, you cannot divide by the ratings.length for every iteration, you will need to divide the total returned after all iterations are done.

1 Like

There actually is a way to do it on each iteration, but that isn’t the way to do it. I do agree though that doing it “after all iterations are done” is a better way, more clear.

1 Like

Thank you I figured it out! But do you mind showing me the way to do it on each iteration, as I ended up doing this:

const ratings = mappedList.map(ratings => (ratings['imdbRating']))

 //console.log(ratings)

 var averageRating = ratings.reduce((total, rating) => {

    //console.log('total', total)

    //console.log('rating', rating)

    return (rating + total)}, 0)

    averageRating = averageRating / ratings.length

  // Only change code above this line

  return averageRating;

}

console.log(getRating(watchList));

Well, you were dividing the running total. Instead you could do the value that you are adding to the running total, before it is added to the running total. Remember:

(A + B + C) / 3

is the same as:

A/3 + B/3 + C/3

What you were doing is (I think):

(((A / 3 + B) / 3) + C) / 3

3 Likes

What you’re doing is I think equivalent to:

A/27 + B/9 + C/3

And just to be clear again, I still think doing the division at the end is better - you only do it once and I think that is easier to read because it is closer to what we think of when we think of computing an average.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.