# Use the reduce Method to Analyze Data - what's wrong?

Use the reduce Method to Analyze Data - what's wrong?
0

#1

Hello guys!
It is printing “8.88.698.3”
Thank you,
Kuba

``````var filterByNolan = watchList.filter(function(item){
return item.Director == "Christopher Nolan"
});

var ratingList = filterByNolan.map(function(element){
var rating = [];
rating.push(Number(element.imdbRating));
return rating;
});

var averageRating = ratingList.reduce(function(prev, next){
return prev + next;
});
console.log(averageRating);
``````

#2

There’s a few things that are going on here.

``````var ratingList = filterByNolan.map(function(element){
var rating = [];
rating.push(Number(element.imdbRating));
return rating;
});

``````

In the code above your are returning an array for each time you loop with the map function. The results will be something like `[[8.8], [8.6], [9], [8.3]]`. Its looks like the default behaviour of performing an add on arrays is to concatenate the results into a string.

You need to fix your map so that it returns a number for each iteration not an array:

``````var ratingList = filterByNolan.map(function(element){
return Number(element.imdbRating);
});
``````

Hint: Your could do all this in one reduce function. On each iteration of reduce you can check the item.director.

Also at the end you will need to divide the total by the array length.

#3

But I have to store map results in some empty array. Your fix is not working
How to do it so in the end will be `[8.8, 8.6, 9, 8.3]`?

Here is the link to challenge CHALLENGE BETA

#4

No you do not. The map function returns a new array, so you can just assign it to a variable as @collinstommy did above. Can you post your revised code, so we can take a look at how you implemented what @collinstommy suggested?

#5

I wrote “Nolsan” in filter function… That’s why it didn’t work

``````var filterByNolan = watchList.filter(function(item){
return item.Director == "Christopher Nolan"
});

var ratingList = filterByNolan.map(function(element){
return Number(element.imdbRating);
});

var averageRating = ratingList.reduce(function(prev, next){
return prev + next/ratingList.length;
},0);
console.log(averageRating);
``````

#6

Now that you solved the challenge, you can simply your solution in two ways.

1. Getting rid of map step and do the Number conversion in the reduce function results in:
``````var filterByNolan = watchList.filter(function(item){
return item.Director == "Christopher Nolan"
});

var averageRating = filterByNolan.reduce(function(prev, next){
return prev + Number(next.imdbRating)/filterByNolan.length;
},0);

console.log(averageRating);  // 8.675
``````

OR

1. Get rid of both the filter and the map steps and do everything in the reduce:
``````var nolanCount = 0;
var averageRating = watchList.reduce(function(prev, next){
return next.Director !== "Christopher Nolan" ? prev : (nolanCount++, prev + Number(next.imdbRating));
},0)/ nolanCount;

console.log(averageRating); // 8.675
``````

Finally, if you do not want to use a global variable like nolanCount, you could use an object as the accumulator argument like:

``````var totalAndCount = watchList.reduce(function(prev, next){
return next.Director !== "Christopher Nolan" ? prev : (prev.count++, prev.total += Number(next.imdbRating), prev);
}, {total: 0, count: 0});
var averageRating = totalAndCount.total / totalAndCount.count;
``````

#7

Just to note, when I went through this challenge, it is important to call reduce() with a initial value of 0. Otherwise, it assumes that the accumulator is an array.

#8

The reduce method accepts these params, `preValue`, `currValue`, `index`.

If you provide an initial value, then `preValue` will be equal to that.

If you do not provide an initial value, then `preValue` will be the value of the first item in the array the method was called on.

Ex:

``````/*
*  No initial value
*  prev -> 1
*  curr -> 2
*/
[1, 2].reduce((prev, curr) => {})

/*
*  Initial value
*  prev -> 0
*  curr -> 1
*/
[1, 2].reduce((prev, curr) => {}, 0)

``````