[Another solutions?] ES6: Write Higher Order Arrow Functions

Hi everyBuddy,

I actually figured it out, but I want to know how you guys would solve this with different approaches.

The problem asks you to return a new array with only positive integers that are squared. So:

  1. Expected new array: [4, 42, 6]
  2. Expected output: [16, 1764, 36]
const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34];
const squareList = (arr) => {
  "use strict";
  // change code below this line
  const squaredIntegers = arr;
  // change code above this line
  return squaredIntegers;
};
// test your code
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);

Hereā€™s how I do it

// change code below this line
const filterdArr = arr.filter(num => num > 0 && (num % 2 === 0 || num % 2 === 1));
const squaredIntegers = filterdArr.map(num => num * num);
// change code above this line

I used .filter() to filter the positive integers first, then used .map() to return a new squared array.

I have 2 concerns:

  1. Is there another way to determine whether a number is integer?
  2. Can I solve this without using filter first? Or more sophisticated (maybe complicated), is there a way I can use .filter() as nested with .map(), so I donā€™t need to declare filteredArr.

Thanks everyone!

Hi

Yes. If you divide by 1 and there is no remainder then it would be an integer. (Check that it is not zero too)

num % 1 === 0

Yes. Many array methods return an array so can be chained. I would still filter first, then map as it seem clearer to me (and why do a math operation on a number that you are discarding anyways?)

const squaredIntegers = arr
		.filter(num => num > 0 && (num % 2 === 0 || num % 2 === 1))
		.map(num => num * num);

	// change code above this line

Normally you could return the result of this directly without saving to a local variable but the challenge as written implies that you save that to a local variable squaredIntegers and then return the value of that variable.

4 Likes

Ha! Youā€™re right. If thereā€™s some fraction then the remainder of dividing by 1 is not 0. Thatā€™s simple but clever! Why didnā€™t I think of that?

Also, you remind me that chaining is not unusual in JS. Itā€™s just that I donā€™t use if often so I canā€™t think of it. And since other numbers are filtered, thereā€™s no reason for .map() to do math operation on them. I guess itā€™s your point on ā€œnested .filter()ā€.

Thanks @alhazen1

Using the test [4, 5.6, -9.8, 3.14, 42, 6, 8.34]
Filter first makes sense because

Filter 7 times + square 4 times = 11 operations
vs
Square 7 times + filter 7 times = 14 operations

Iā€™m sure you could come up with a single method solution using reduce() where

  1. you test for integer
  2. and if integer square
  3. then push square to accumulator array

but that would be harder to understand at a glance and I donā€™t know that it would run any faster. Unless you were repeating the operation many times probably not even worth checking which is fastest.

2 Likes
1 Like

Interesting solutions!
Hereā€™s mine

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

I already solved this using map(num => num * num); but I donā€™t know why map(num => num ^ 2); doesnā€™t work

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 = realNumberArray.filter(num => num % 1 === 0 && (num > 0)).map(num => num ^ 2);
  // change code above this line
  return squaredIntegers;
};
// test your code
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);

Hi, Iā€™m stucked in this challenge and taking a look at your answer I cannot understand how the word num that you used in the filter and map methods is defined. How can that method know what num is?

Hi,
These two array methods iterate through the array. Each iteration they pass 4 parameters to your callback - the item (which Iā€™ve called num), the index of that item, the entire array and a value to use as ā€˜thisā€™. These get passed whether you use them or not - in this case we are only using the first one.

Here is a contrived example showing that the first three of those parameters did indeed get passed each iteration

MDN is my favorite reference for array methods. The callback parameters are listed under the Syntax section for each method. Method links are listed down the left of each page


But you didnā€™t declare num anywhere in the code, so I cannot understand how if you put the word num there for the first time knows exactly what it is.

It is all done inside the map method - we donā€™t see that code.

This is probably a gross oversimplification but inside the map method the user-supplied callback is called something like this

let newArray = [];

for(let i = 0; i < thisArray.length; i++){
  newArray[i] = callback(thisArray[i], i, thisArray);
}

return newArray

num would be the thisArray[i] that gets passed each iteration.

Iā€™m sorry, I donā€™t see it yet. If you use any other word like number or integer or something like that it would work properly?

Hi,
Short answer - yes. num is just variable local to the callback so name it anything.

Let me explain a different way with an example building up to map. I think once you discover that map is just a fancy for loop that does something to each element youā€™ll see why it does not matter what you name the function arguments in your callback.

.map() does ā€œsomethingā€ to each element of an array and saves the results of that something in a new array. That something is your whatever you callback does.

For instance, you have an array of numbers and you want a new array of those numbers tripled. Without array methods you could do this with a for loop.

const arr = [1,2,3,4];
let newArray = [];

for(let i = 0; i < arr.length; i++){
  newArray[i] = arr[i] * 3;
}

console.log(newArray);  //[ 3, 6, 9, 12 ]

Maybe you already have a function that triples a number. You could use that in your for loop too.

const arr = [1,2,3,4];
newArray = [];

// your triple function
function triple(someNum){
  return someNum * 3;
}

for(let i = 0; i < arr.length; i++){
  newArray[i] = triple(arr[i])
}

console.log(newArray);  //[ 3, 6, 9, 12 ]

You can do the same with map. It takes care of the for loop for you. Really you just provide the ā€œsomethingā€ that gets performed on each element - a callback that triples a number.

const arr = [1,2,3,4];
newArray = arr.map(function(someNumber){
  return someNumber * 3;
});

console.log(newArray); //[ 3, 6, 9, 12 ]

Since it looks like this challenge is using arrow functions we can do that too.

const arr = [1,2,3,4];
const newArray = arr.map( aNum => aNum * 3);
console.log(newArray); //[ 3, 6, 9, 12 ]

In fact, you could even use your triple function from the earlier example with map.

const arr = [1,2,3,4];

const newArray = arr.map(triple);
console.log(newArray);  //[ 3, 6, 9, 12 ]

OK - about those names in callback argument list. Revisiting the second example notice that it makes no difference what we call that number in the triple function. Also notice that sending extra parameters (like map does) changes nothing - the extras are simply ignored.

const arr = [1,2,3,4];
newArray = [];

// my triple function
function triple(x){  // NEW local variable name x makes no difference
  return x * 3;
}

for(let i = 0; i < arr.length; i++){
  newArray[i] = triple(arr[i], i, arr);  // sending more parameters makes no difference
}

console.log(newArray);  //[ 3, 6, 9, 12 ]

Same when using map. Changing argument name makes no difference.

const arr = [1,2,3,4];
const newArray = arr.map( theNum => theNum * 3);
console.log(newArray); //[ 3, 6, 9, 12 ]
3 Likes

Thank you for that explanation. I get it now. Itā€™s hard for me to think in a programming wayā€¦ Now I see it very clear, thank you again!

i liked the way you explained that case. was helpful to me thank you buddy