嵌套 ES6 数组辅助方法以生成素数数组
Nesting ES6 array helper methods to generate an array of prime numbers
所以我想写一个函数 returns 所有质数的总和,直到并包括提供的数字。
我写了这个,有效:
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);
我在想,如果将 for 循环替换为另一个数组辅助方法,它看起来会更整洁。然而,我正在努力实现这一点。
这是我目前得到的:
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);
这样写,函数不再按预期工作——它不过滤任何数字,所以所有数字都由 .reduce 助手求和。控制台使它看起来像 if 语句仍在按预期工作;我做错了什么?
您的代码无法使用 find 的原因是因为 find
不是 for
循环的合适替代品。 for
循环 return 是一个布尔值,指示是否找到除数。 find
另一方面,return 是除数本身。这意味着您的 filter
方法的所有条件都是大于 1 的数字,它们都被评估为真实的,因此没有任何东西被过滤。
更适合您的用例的方法是 some or every。
这些基本上像 find
一样工作,除了 return 一旦找到满足条件的元素就会返回一个布尔值。
some
停止并且 returns true
一旦谓词函数 returns true
用于某些元素。
否则它 returns false
.
every
停止并且 returns false
一旦谓词函数 returns false
用于某些元素。
否则它 returns true
.
还有一个问题是,使用这样的帮助器会使您的代码效率降低,因为您现在正在检查所有数字,而不仅仅是当前数字。这意味着您的谓词函数也必须包含此相等性检查,否则您必须首先过滤数组以查找被检查元素下方的所有元素。
效率方面的另一个小改进是您不需要一直迭代到 element - 1
来找到除数。迭代到 sqrt(element)
就足够了,因为所有高于 sqrt(element)
的除法元素都将在 sqrt(element)
.
下面的某处有一个补数除数
这是一种使用 every
并过滤低于被检查元素平方根的元素的方法。
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
也许功能较少但效率更高(恕我直言,同样干净)的方法是将您的 for
循环转换为辅助函数:
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
您可以缩小 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));
所以我想写一个函数 returns 所有质数的总和,直到并包括提供的数字。
我写了这个,有效:
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);
我在想,如果将 for 循环替换为另一个数组辅助方法,它看起来会更整洁。然而,我正在努力实现这一点。
这是我目前得到的:
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);
这样写,函数不再按预期工作——它不过滤任何数字,所以所有数字都由 .reduce 助手求和。控制台使它看起来像 if 语句仍在按预期工作;我做错了什么?
您的代码无法使用 find 的原因是因为 find
不是 for
循环的合适替代品。 for
循环 return 是一个布尔值,指示是否找到除数。 find
另一方面,return 是除数本身。这意味着您的 filter
方法的所有条件都是大于 1 的数字,它们都被评估为真实的,因此没有任何东西被过滤。
更适合您的用例的方法是 some or every。
这些基本上像 find
一样工作,除了 return 一旦找到满足条件的元素就会返回一个布尔值。
some
停止并且 returnstrue
一旦谓词函数 returnstrue
用于某些元素。 否则它 returnsfalse
.every
停止并且 returnsfalse
一旦谓词函数 returnsfalse
用于某些元素。 否则它 returnstrue
.
还有一个问题是,使用这样的帮助器会使您的代码效率降低,因为您现在正在检查所有数字,而不仅仅是当前数字。这意味着您的谓词函数也必须包含此相等性检查,否则您必须首先过滤数组以查找被检查元素下方的所有元素。
效率方面的另一个小改进是您不需要一直迭代到 element - 1
来找到除数。迭代到 sqrt(element)
就足够了,因为所有高于 sqrt(element)
的除法元素都将在 sqrt(element)
.
这是一种使用 every
并过滤低于被检查元素平方根的元素的方法。
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
也许功能较少但效率更高(恕我直言,同样干净)的方法是将您的 for
循环转换为辅助函数:
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
您可以缩小 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));