【问题标题】:Why won't my function work when I use splice?为什么我使用 splice 时我的功能不起作用?
【发布时间】:2018-08-29 17:09:48
【问题描述】:

我正在尝试编写一个函数,它应该计算所有素数直到输入参数并返回它。我这样做是为了练习。

我以几种方式编写了此函数,但我试图找到新的方法来执行此操作以进行更多练习并获得更好的性能。我最后尝试的是下面的代码:

function primes(num){
  let s = []; // sieve
  for(let i = 2; i <= num; i++){
    s.push(i);
  }
  for(let i = 0; i < s.length; i++) {

    for(let j = s[i]*s[i]; j <= num;) {
      //console.log(j);
      if(s.indexOf(j)!= -1){

        s.splice(s.indexOf(j), 1, 0);

      }
      j+=s[i];
    }
  }
  s = s.filter(a => a != 0);
  return s;
}
console.log(primes(10));

问题是当我在浏览器中运行它时,它一直在计算并且不会停止,我不知道为什么。

注意:当我注释掉 splice 并取消注释 console.log(j); 时,一切都按预期工作,日志应该是它们应该有的东西,但是使用 splice,浏览器会继续计算并且不会停止。

我使用的是最新版本的 Chrome,但我认为这与问题无关。

【问题讨论】:

    标签: javascript sieve-of-eratosthenes


    【解决方案1】:

    你的问题出在这一行:

    s.splice(s.indexOf(j), 1, 0);
    

    Splice 函数的第三个参数包含要添加的元素以代替已删除的元素。这意味着您不是删除元素,而是将它们的值与 0 交换,然后冻结您的 j 循环。 要修复它,只需省略第三个参数。

    function primes(num){
      let s = []; // sieve
      for(let i = 2; i <= num; i++){
        s.push(i);
      }
      for(let i = 0; i < s.length; i++) {
    
        for(let j = s[i]*s[i]; j <= num;) {
          //console.log(j);
          if(s.indexOf(j)!= -1){
    
            s.splice(s.indexOf(j), 1);
    
          }
          j+=s[i];
        }
      }
      return s;
    }
    console.log(primes(10));

    【讨论】:

    • 做这个修复,最后你也可以去掉filter()函数
    • @CalvinNunes 当然你是对的,我不知道我怎么没有注意到它。 :)
    • 啊,谢谢。我实际上是先这样做的,但我记得它没有用,我可能还有另一个问题,当时我没有发现。我想可能是通过更改数组中的索引,我的 for 循环错过了几个数字,所以我故意添加零以避免这种情况。我对自己很失望:))。非常感谢你。 :)
    【解决方案2】:

    你的问题在这个循环中:

    for(let j = s[i]*s[i]; j &lt;= num;)

    这个 for 循环将永远循环,因为无论您在测试什么情况下,j 总是小于或等于 num。很难准确确定这段代码何时开始无限循环,因为您在循环时正在修改列表。

    实际上,splice 命令将被调用,将s 中的部分索引设置为 0,这意味着j+=s[i] 将不再让您脱离循环。

    【讨论】:

    • 实际上不难意识到该代码何时将无限循环。一旦 i-loop 落在一个先前被交换为 0 的元素上(splice 第三个参数!),它就会发生,因为通过乘以零,条件j &lt;= num 将始终为真。
    • 当然可以,但是哪些索引将设置为零?不是那么容易推理的。事实上,它似乎至少有两种不同的情况可以无限循环。
    • 嗯,在当前代码中,您已经可以看到它会在 i = 2 时立即停止(这意味着元素将为 4,但由于它是 2 的乘积,因此它之前设置为 0 )
    • 是的,我明白了。我必须计算出 i = 0 和 1 才能确信它在此之前不会循环,只是说确定它并非易事。只是从代码中可以清楚地看出,这些条件最终会得到满足。
    • 谢谢。 :) 我不知道为什么我没有看到。我真的对自己很失望。
    猜你喜欢
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多