## Nesting ES6 array helper methods to generate an array of prime numbers

Question

So I wanted to write a function that returns the sum of all prime numbers up to and including a provided number.

I have written this, which works:

``````function sumPrimes(num) {
const arr = Array.from({length: num+1}, (v, k) => k).slice(2);
return arr.filter(element => {
for(let i = 2; i < element; i++) {
if(element % i === 0) {
return false;
}
}
return element;
}).reduce((previous, current) => {
return previous += current;
}, 0);
}

sumPrimes(9);``````

I was thinking it would look much neater if the for loop was replaced with another array helper method. I'm struggling with the implementation of this however.

This is what I've got so far:

``````function sumPrimes(num) {
const arr = Array.from({length: num+1}, (v, k) => k).slice(2);
return arr.filter(element => {
return arr.find(ref => {
console.log("(" + element + " % " + ref + " === 0) " + (element % ref === 0));
if(element % ref === 0) { return false; }
return true;
});
}).reduce((previous, current) => {
return previous += current;
}, 0);
}

sumPrimes(20);``````

Written like this, the function no longer works as expected – it doesn't filter any of the numbers so all are summed by the .reduce helper. The console makes it appear like the if statement is still working as desired; what am I doing wrong?

Show source

## Answers to Nesting ES6 array helper methods to generate an array of prime numbers ( 2 )

1. The reason your code doesn't work using find is because `find` is not a proper replacement for your `for` loop. The `for` loop you have here returns a boolean indicating if a divisor is found. `find` on the other hand, returns the divisor itself. This means all conditions for your `filter` method are numbers above 1, which all evaluate as truthy and hence nothing gets filtered.

The more appropriate method for your use case would be some or every. These essentially work like `find`, except return a boolean as soon as they find an element satisfying the conditions.

• `some` stops and returns `true` as soon as the predicate function returns `true` for some element. Otherwise it returns `false`.

• `every` stops and returns `false` as soon as the predicate function returns `false` for some element. Otherwise it returns `true`.

One more issue would be that using a helper like this makes your code less efficient because you're now checking all numbers and not just up to the current number. This means your predicate function must include this equality check as well, or you'll have to first filter the array for all elements bellow the element being checked.

Another small improvement in terms of efficiency is that you don't need to iterate all the way up to `element - 1` to find a divisor. Iterating up to `sqrt(element)` is enough because all numbers higher than `sqrt(element)` that divide element will allready have a complement divisor somewhere bellow `sqrt(element)`.

Here's an approach using `every` and filtering the elements bellow the square root of the element being checked.

``````function sumPrimes(num) {
const arr = Array.from({length: num+1}, (v, k) => k).slice(2);
return arr.filter(element => {
return arr
.filter(ref => ref*ref <= element)  // filter elements less than sqrt(current)
.every(ref => element % ref !== 0); // filter elements that have a divisor
}).reduce((previous, current) => {
return previous += current;
}, 0);
}

console.log(sumPrimes(9)); // 17``````

Perhaps a less functional but more efficient (and IMHO equally clean) way would be to just convert your `for` loop into a helper function:

``````function isPrime(element) {
for(let i = 2; i*i <= element; i++) {
if(element % i === 0) {
return false;
}
}
return true;
}

function sumPrimes(num) {
return Array
.from({ length: num+1 }, (v, k) => k)
.slice(2)
.filter(isPrime)
.reduce((previous, current) => previous += current, 0);
}

console.log(sumPrimes(9)); // 17``````

2. You can reduce the range of research for primality of n at sqrt(n) :

``````var isPrime = n => n===2 ? true : Array(Math.ceil(Math.sqrt(n))+1).fill().map((e,i)=>i).slice(2).every(m => n%m);

var sumPrimes = num => Array(num).fill().map((e,i)=>i+1).slice(1).filter(isPrime).reduce((a,b) => a+b);

console.log(sumPrimes(9));``````