Sum All Primes? I don't get it

Tell us what’s happening:
I am trying to sort out this challenge. My function creates an array with n numbers. What I am trying to do is to filter such array with filter method and a nested for loop. In theory it should filter only those numbers that return true inside the for loop. If I try to run the function passing 10 as argument, the function returns [1,3,5,7,9].

I don’t understand why 9 is filtered.

  **Your code so far**
function sumPrimes(num) {
let newArr = Array.from(Array(num).keys());
return newArr.filter(el => {
  for (let i = 2; i<num; i++){
    return (el%i!=0)
  }
})
}

sumPrimes(10);

Challenge: Sum All Primes

Link to the challenge:

  1. List item

Let’s look at that for loop:

for (let i = 2; i<num; i++){
    return (el%i!=0)
  }

Explain to me in regular language (not code) what this is doing?

OK, the cat’s out of the bag. The for loop is only running once and thus you are basically testing if the number is odd.

1 Like

For what it’s worth, this is a very slow approach, and I would think of a way to do this with zero arrays.

The issue with your filter is that you have a return statement inside of a loop. The loop will only iterate once.

In my head it should return an array filtered with elements the return module <> 0 for all the for loop iteration. For example 6, is not filtered because the module is 0 when the for loop hit i=3.

Your for loop will never get to i=3. Do you see why?

1 Like

I think I got it now. They all stop at i=2? the return made all the iteration stop at i=2. (1,3,5,7,9) return <> 0 at i=2. The iteration stop running for each element.

1 Like

Correct. BTW 2 is a prime number but it’s excluded by your function.

To make your function work as intended, try:

  • Tightening up your i ranges (you should be able to cut each down by at least half)
  • Revise your return conditions (you may need two return's; one inside and the other outside the for loop)

I tired with this:

function sumPrimes(num) {

let newArr = Array.from(Array(num).keys());

return newArr.filter(el => {
  for (let i = 2; i < Math.sqrt(num);  i++){
    if (el % i  === 0) return false;
  }
  return true
})
}

sumPrimes(10);

The problem I got is that in this example when I test the function passing 10 as the argument the three is divided by itself and is considered not prime. Any advise to help me to overcome the stall?

Math.sqrt(3) is 1.73… which is less than 2. So the for loop body won’t get executed, thus should return true.

BUT…

You’re not computing Math.sqrt(3) when el is 3. You’re always computing Math.sqrt(num).

Also, you better check the content of newArr. Is newArr really [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]?

This code makes only a list of primes (again, making and filtering an array is one of the least efficient ways to to this and I strongly recommend you just use a raw loop over the values rather than going through all of the trouble to allocate an array and then filter it!!)

Where are you suming the primes? The name of the function is sumPrimes after all.

The optimal i range for each el depends on el, not num :wink:

Also note @twotani and @JeremyLT 's comments.

FYI, putting a for-loop inside a filter function isn’t usually a good idea. If you have to put a loop inside a filter function like that, that’s a sign you’re doing something wrong. Would highly recommend re-working to get rid of the for-loop. There’s definitely a way to get to a solution that doesn’t have that.

At a high level this is an approach that I would personally take (there are certainly other correct and more efficient ways to go as well):

  1. Create an array consisting of numbers from 1 to “num”
  2. Filter the previous array for all prime numbers
  3. Sum the filtered array

Btw yes I recognize that my step 1 is very inefficient. And on second thought, you don’t need to even do that. I’ll leave it as an exercise what would be efficient. :wink:

Don’t make an array. Don’t make an array. Don’t make an array.

It’s the absolute slowest, least efficient solution possible. (Without intentionally trying to make an obscure, slow solution)

I prefer using high order methods like map and filter, but this is a situation where raw loops are fastest and clearest, since JavaScript does not have proper range objects like other high level languages.

1 Like

Yes, beginners can mix up the filter and regular loop and put those in one place in a wrong way. But in this case, you need some form of loop to determine whether an element is a prime or not.

As to the use of an array and filtering it, I have a mixed feeling, but more toward accepting it if a functional style of coding (map, filter, reduce) is involved. I’m a very old school, remembering the days when a personal computer had something like 64K memory, so I too have aversion toward using an array when it is not necessary. But being familiar with the functional style of coding is so critical in mastering JS frameworks, I think the use (generation) of an array here is acceptable, just for the sake of learning map/filter/reduce. The solution would adapt nicely if we change the question to “Compute the sum of prime numbers in a given array of positive integers.”

My two cents.

Building an array just to be able to loop over the numbers from 2 to n is not functional programming - its just making code slow for no good reason.

JavaScript doesn’t properly support the range objects needed to do this challenge correctly in a functional way. Part of mastering JS is understanding its limitations. Purism in following any coding paradigm - functional, OO, imperative - leads to bad code.

A better way to practice functional, modular code would be to make a prime checking function. That function could be independently refactored and could be incorporated into a loop based solution or a range iterator based solution in a language with proper range support.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.