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?
The reason your code doesn't work using find is because
find
is not a proper replacement for yourfor
loop. Thefor
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 yourfilter
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 returnstrue
as soon as the predicate function returnstrue
for some element. Otherwise it returnsfalse
.every
stops and returnsfalse
as soon as the predicate function returnsfalse
for some element. Otherwise it returnstrue
.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 tosqrt(element)
is enough because all numbers higher thansqrt(element)
that divide element will allready have a complement divisor somewhere bellowsqrt(element)
.Here's an approach using
every
and filtering the elements bellow the square root of the element being checked.Perhaps a less functional but more efficient (and IMHO equally clean) way would be to just convert your
for
loop into a helper function: