Getting the square with reduce()

Tell us what’s happening:
Describe your issue in detail here.
It says reduce is not defined when I run my code. Can someone clarify what that means?

  **Your code so far**

const squareList = arr => {
// Only change code below this line
let myArr = arr;
myArr = arr.
 filter(num => Number.isInteger(num) && num > 0)
 console.log(myArr);
 reduce((myArr, num) => myArr.push(num * num));
 console.log(myArr);
return myArr;
// Only change code above this line
};

const squaredIntegers = squareList([-3, 4.8, 5, 3, -3.2]);
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/96.0.4664.110 Safari/537.36

Challenge: Use Higher-Order Functions map, filter, or reduce to Solve a Complex Problem

Link to the challenge:

.reduce() is a method on an array. You can’t stick a bunch of ;s and console.log()s between the arr. and reduce().

It is fine (and recommended) to chain .filter() and .reduce() though.

I put the console.log()s to see where the problem occurs and the first part seems correct, however, reduce is still undefined when I remove the console.log()s. I am probably making a mistake with the way I design .reduce().

Did you also remove the ; after the filter?

Woops, don’t see one. Seeing new code would help.


I wouldn’t use a reduce here.

Remove item from array → filter

New array from old array → map

More complicated thing → reduce


But yea, your reduce can’t work like that. You’re probably getting some sort of an error about .push(). You can’t push onto a number, but when you don’t provide an initial value for .reduce(), the first element of the array is used.

1 Like
const squareList = arr => {
  // Only change code below this line
  let myArr = arr;
  myArr = arr.
   filter(num => Number.isInteger(num) && num > 0)
   reduce((myArr, num) => myArr.push(num * num));
  return myArr;
  // Only change code above this line
};

const squaredIntegers = squareList([-3, 4.8, 5, 3, -3.2]);
console.log(squaredIntegers);

Yea, see the last part of my reply in particular, but I wouldn’t use a reduce here anyways.

1 Like

The code you posted doesn’t work because you are missing a period before reduce. Often I put them in front of the method:

  myArr = arr
    .filter(num => Number.isInteger(num) && num > 0)
    .reduce((myArr, num) => myArr.push(num * num));
2 Likes

Yeah, that too. The dot goes with the method to prevent insanity.

1 Like

But I agree, that reduce isn’t the right method here. reduce is for taking an array down to a value. What you want is a method that takes one array and makes a new array where each element in the new array is made from the corresponding element in the old array.

2 Likes

Also note that your callback is shadowing myArr, which you have 3 different definitions of in your code. That’s also a good way to go mad debugging.

1 Like

How do I provide an initial value in the case of an array? Does the method introduced in the challenge that explains reduce would work? It was like this:

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const sumOfAges = users.reduce((sum, user) => sum + user.age, 0);
console.log(sumOfAges);

But I doubt it would be the same for an array because it seems to me that the 0 at the end just initialized the sum.

Well, 0 does initialize a sum but you want to initialize an array… So use an array.

(Though, again, reduce is a bad fit here)

Yeah, I will change it to map() but I was just curious if there is a way to make reduce work here.

You can always reproduce a map or filter as a reduce if you initialize your accumulator as an array.

In this case the accumulator would be the filtered array, is that right?

Depends on where you put it? I would initialize with an empty array.

You could do this with reduce, but it would have to be a different method than what you are doing. Personally, I prefer the approach you are doing - it will be more readable.

Yeah, I will change it to map()

Ding ding ding!

I was just curious if there is a way to make reduce work here

Yes you could. In fact, you could use only that. You accumulator would be the array you want.

And yes, with your 2 method approach (which again, I think is better because it is more readable, you could replace either of those methods with reduce - it’s just not a good idea - again, readability.

But that might be a good exercise - write your own mapping, filtering, and finding methods (or just as functions) using only reduce. reduce is a hard method for new people to understand. But that would help.

1 Like

I checked the solution that uses reduce and is the at the end where the array is initialized?

const squareList = arr => {
  return arr.reduce((sqrIntegers, num) => {
    return Number.isInteger(num) && num > 0
      ? sqrIntegers.concat(num * num)
      : sqrIntegers;
  }, []);
};

Yeah. You wouldn’t want to start with a full array, then you’d have extra values in there that don’t match your target results.

1 Like

Okay, it is more clear for me now. Thank you all for the help!

1 Like