嵌套ES6数组辅助方法以生成素数数组

时间:2017-01-02 15:23:04

标签: javascript arrays ecmascript-6 primes helpers

所以我想写一个函数,它返回所有素数的总和,包括提供的数字。

我写过这个,有效:

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语句看起来仍然可以正常工作;我做错了什么?

2 个答案:

答案 0 :(得分:3)

您可以在sqrt(n)处缩小 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));

答案 1 :(得分:2)

您的代码无法使用find工作的原因是find不适合您的for循环。这里的for循环返回一个布尔值,表示是否找到了除数。另一方面,find返回除数本身。这意味着您的filter方法的所有条件都是大于1的数字,所有条件都评估为真实,因此不会过滤任何内容。

更适合您的用例的方法是someevery。 这些基本上像find一样工作,除了在找到满足条件的元素时返回一个布尔值。

    只要谓词函数为某个元素返回some
  • true就会停止并返回true。 否则返回false

  • 只要谓词函数为某个元素返回every
  • false就会停止并返回false。 否则返回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并过滤被检查元素的平方根旁边的元素的方法。

&#13;
&#13;
for
&#13;
&#13;
&#13;

可能功能较少但效率较高(和恕我直言同样干净)的方法是将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循环转换为辅助函数:

&#13;
&#13;
d = df.groupby('userId').apply(lambda y: {int(x.movieId): x.rating for i, x in y.iterrows()})
      .to_dict()
print (d)
{
1: {1129: 2.0, 1061: 3.0, 1172: 4.0, 1029: 3.0, 31: 2.5}, 
2: {1111: 4.5, 31: 3.0}
}
&#13;
&#13;
&#13;