Hi.
I have solved this problem a few different ways while trying to get to grips with the reduce method, but I wasn’t really happy with them. My other solutions relied on global variables and/or chaining .filter()
or .filter().map()
with .reduce()
.
I was determined to find a way to do it using only .reduce()
, and no external variables.
I suspect its probably poor technique for a number of reasons, but I’m still pretty amused that I managed to get it to work at all. What do you think?
var averageRating = watchList.reduce( (a,c,i,arr) => {
if(a === 0) {
a = {rating: 0, nolans: 0};
}
if(c.Director === "Christopher Nolan") {
a.nolans++;
a.rating += Number(c.imdbRating);
}
return i < arr.length - 1 ? a : (a.rating / a.nolans);
}, 0);
It doesn’t have much reusability, which doesn’t matter in this case, but not bad overall.
You can just do this to avoid having unnecessary if branch:
watchList.reduce(..., { nolans: 0, rating: 0 })
And use parseFloat()
instead of Number()
I often do it this way, if I want to be functional and reusability is a concern:
const by = (key, val) => (obj) => obj[key] === val
const extract = (key) => (obj) => obj[key]
const toFloat = (str) => parseFloat(str)
const sum = (a, b) => a + b
const average = (arr) => arr.reduce(sum) / arr.length
const averageRating = average(
watchList
.filter( by('Director', 'Christopher Nolan') )
.map( extract('imdbRating') )
.map( toFloat )
)
1 Like
oh, nice.
I like the way you’ve broken it down, and that seems more functional (which is something I’m just really trying to get a handle on), and I usually like to make things are reusable as possible.
I think I need to spend a bit of time reading over by
and extract
- I haven’t seen chained arrow notation functions before, and it feels a bit slippery to understand at first glance atm.
What’s the reason for using parseFloat()
over Number()
? After I wrote my solutions and googled around, I noticed that other people have also gone with parseFloat()
It feels like my brain is melting looking at that, haha!
Do you do code golf by any chance?
After a few search, I’ve concluded that It doesn’t really matter whether you use parseFloat()
or Number()
as long as you don’t call the latter with new
operator. In general, parseFloat()
is less strict than Number()
, but they both have inconsistent edge case handling. So, just forget about it I guess.
You don’t really need by
and extract
, they are just there to enhance readability for averageRating
. I had to split it like that to use them in filter
and map
.
Even if you haven’t seen it before, the concept isn’t so difficult.
fn = (a, b, c) => // use a, b, c
fn = a => b => c => // use a, b, c
function fn(a) {
return function(b) {
return function(c) {
//use a, b, c
}
}
}
those functions do the same task, but the second function is more flexible because you can supply arguments across different scopes or you can compose other functions with some pre-supplied arguments.
1 Like
I am looked for ,but how?
how to hide code from other?
I just take half of code from upper and set it in other form. Probably is not functional in exercise.
Ah!
Seeing it written out in long-form made it click immediately, nice one!