edmassarani
edmassarani

Reputation: 298

access the array object inside a higher order function

I'm trying to access the length of the array on which I'm using a reduce function inside that reduce, but I don't seem to be able to do it, does anyone have any idea if it is possible to access the array object inside any of the higher order functions?

PS: I tried using this but to no success;

PSS: I want to calculate the average rating using a reduce function, so I use the reduce to sum all values in the array and divide those same values by the array length, like so:

let averageRating = watchList
    .filter(movie => movie.Director === 'Christopher Nolan')
    .map(x => parseFloat(x.imdbRating))
    .reduce((total, current) => total + (current / 'array length'));

where 'array length' would be, you guessed it, the array length.

PSSS: Tried

var averageRating = watchList
  .filter(movie => movie.Director === 'Christopher Nolan')
  .map(x => parseFloat(x.imdbRating))
  .reduce((total, current, index, arr) => total + (current / arr.length));

but the array length keeps changing as the array is being reduced, so it wouldn't work for my purposes.

Upvotes: 7

Views: 491

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50787

This should do it:

let averageRating = watchList
    .filter(movie => movie.Director === 'Christopher Nolan')
    .map(x => parseFloat(x.imdbRating))
    .reduce((total, current, idx, arr) => total + (current / arr.length));

Update

If you're interested in seeing how I would do it in my preferred library, Ramda (disclaimer: I'm one of its principle authors) the code would like like this:

const {pipe, filter, propEq, pluck, map, mean} = R;

const watchList = [{"Director": "Christopher Nolan", "imdbRating": 4.6, "title": "..."}, {"Director": "Michel Gondry", "imdbRating": 3.9, "title": "..."}, {"Director": "Christopher Nolan", "imdbRating": 2.8, "title": "..."}, {"Director": "Christopher Nolan", "imdbRating": 4.9, "title": "..."}, {"Director": "Alfred Hitchcock", "imdbRating": 4.6, "title": "..."}, {"Director": "Christopher Nolan", "imdbRating": 4.6, "title": "..."}];

const averageRating = pipe(
  filter(propEq('Director', 'Christopher Nolan')),
  pluck('imdbRating'),
  map(Number),
  mean
);

console.log(averageRating(watchList));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

I find this leads to really clean, readable code.

Upvotes: 4

Giannis Mp
Giannis Mp

Reputation: 1299

You can try this:

let averageRating = watchList
        .filter(movie => movie.Director === 'Christopher Nolan')
        .map(x => parseFloat(x.imdbRating))
        .reduce((total, current, index, array) => {
            total += current;
            if( index === array.length - 1) {
               return total/array.length;
            } else {
               return total;
            }
        });

Upvotes: 3

Related Questions