Write Higher Order Arrow Functions - Passing test but not getting the basics

Tell us what’s happening:

I just successfully passed the text on this lesson after days of reading through the forum, googling and checking MDN. Somehow I managed to get to the answer right (or one of the possible answer) without looking at the spoiler in the Hint section. Still, I can’t move on since I don’t think I’m grasping the basics of the lesson.

  1. The solution in the Hint section checks for this condition && num % parseInt(num) === 0 while I’m using Number.isInteger(num). Can someone please explain how the suggested solution works, which one is preferable and why?

  2. Even though it is not explained in previous lessons, I checked the forum and other websites and I think I now understand what .filter and .map are used for and why they help here. However, the test is checking that either filter, map or reduce are used, and I can’t make it work with reduce. Could someone walk me through a solution with reduce?

  3. How does my function know that num is the current value in the array being checked? I found this by accident but I’d like to know how was I supposed to know or infer this.

  4. This last point, I think, is proof that I’m not really getting the lesson: squaredIntegers is created as a constant inside the squareList function. It is testing that the different values in the provided array are integers and positives before squaring them. But then at “test your code” we assign the same squaredIntegers constant the constant/function squareList with the realNumberArray as value. So this is giving me trouble because (a) I thought constants couldn’t be reassigned and (b) I see this as assigning the product of a function to the product itself.

Sorry for the long post. Anyone willing to chime in for any or all of my concerns above will be more than welcomed.

Thanks in advance,

Your code so far


const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2];
const squareList = (arr) => {
  "use strict";
  // change code below this line
  const squaredIntegers = arr.filter((num) => Number.isInteger(num) && num > 0).map((num) => num * num);
  // change code above this line
  return squaredIntegers;
};
// test your code
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/es6/write-higher-order-arrow-functions/

  1. Yours is better and clearer.
  2. Filter and map can be thought of as more specialised of reduce - I’m a bit short on time at the minute but I’ll edit in an explanation when I’ve got time
  3. It doesn’t ‘know’: what you are doing is running a function for every element in the array in order - the one used in the filter is just a function that checks if a value it is given is a positive integer, filter just runs it for each element in turn.
  4. Function scope - the construction inside the function is not the same as the one outside. The way the code is laid out is confusing here - it’s to do with helping the tests run properly, not to help learners.

I’ll try to help you here:

#1

Let’s break this first num % parseInt(num) === 0

  1. num % parseInt(num), parseInt will convert a double to an integer (e.g. 5.5 becomes 5)
  2. % is the remainder operator, it will give what’s left from a division (e.g. 5 % 5.5 becomes 0.5, because 5 / 5 is 1 with a remainder of 0.5.
  3. === 0, checks if that value is 0, in our case, if the remainder operator returned 0 it means our value is an integer. (e.g. our 0.5 === 0, no, so it’s not an integer)

Both solutions works, which is better? In my opinion your solution is way better because it is way more readable.

#2

  1. filter gets an array and filters its element to return only the elements that you want, it filters your array into a new one that you want. (e.g [1, 2, 3].filter(n => n >= 2) is [2, 3])
  2. map goes over every element in your array transforming then into other elements (e.g. [1, 2, 3].map(n => n * 2) is [2, 4, 6])
  3. reduce works in your array to transform your array into a single element (e.g. [1, 2, 3].reduce((total, n) => total + n) is 6)

Since the challenge asks for you to return an array it doesn’t make sense to use reduce there.

#3

filter, map and reduce iterates over your array one by one just like a normal for loop, so num starts as your first element in the array, then the second, etc…

#4

This is because of scope, the squaredIntegers inside the function is a new variable and can be used only inside the function, if you try to create it outside it will give you an error.

1 Like

Thank you, @DanCouper. I’ll look forward to any additional information on how reduce is supposed to be used in this context.

Thank you, @ghukahr!

#1 is perfectly clear now, thanks!
#2 Why is the test looking for reduce if it doesn’t make sense to use it here?
#3 So the same way I used num I could’ve used anything else, provided I use it before =>?
#4 So does this mean that the constant squaredIntegers inside the function is not the same as the const squaredIntegers used to test the function?

#2 reduce is used to reduce an array to a single value, but there’s nothing stopping you from using the accumulator (reduce first argument) to create an array and pushing elements into it (or skipping), which means you can write map, filter or anything with it for example. It’s clumsy and not worth it.

I prefer to think of it as a way to reduce an array to a single value.

The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.

#3 Yes, num is just the name of the parameter, you can use whatever name you like.

#4 It isn’t, you can’t even assign a new value to a constant in the first place. The squaredIntegers inside the function is returned from the function and assigned to the squaredIntegers on the outside of the function. But you could ignore the squaredIntegers inside the function and return, for example, “Hello”. Then squaredIntegers inside the function would contain our array and the squaredIntegers from outside would contain “Hello”.

1 Like
  1. Yup. Like take this:
[1,2,3].map(n => n ** 2)

So map is taking a function that squares each number in the array. That function is just the same as this:

function square(n) {
  return n ** 2;
}

Which could just as well be

function square(abracadabra) {
  return abracadabra ** 2;
}

And if you’re using it as a callback:

[1,2,3].map(abracadabra => square(abracadabra))
// Same as:
[1,2,3].map(square)
// Same as:
[1,2,3].map(function(n) { return n ** 2 })
// Same as:
[1,2,3].map(n => n ** 2)
2 Likes

This was really helpful

I finally get it! I think the post in the FCC example was the source of all my confusion:

FBPosts.filter((post) => post.thumbnail !== null && post.shares > 100 && post.likes > 500)

Thanks a lot.

#2 and #3 are all clear now. Thanks! I’m still trying to wrap my head around #4, though.

How can it be assigned on the outside to itself? Is that because they are two different things? Why then give it the same name?

Anyway, thanks @ghukahr and @DanCouper. You helped me a lot!

You should think of it as two different variables. I don’t know why they give it the same name, they probably shouldn’t, that just makes things more confuse.

Okay, I feel reassured then. I will check the link you provided. Thanks!