繁体   English   中英

虽然循环有两个嵌套的 for 循环输出无限循环,但我做错了什么?

[英]While loop with two nested for loops outputting infinite loop, what am I doing wrong?

我正在制作一个程序,该程序将任意随机的 integer 加起来其各个值并创建一个总和。 如果转换为字符串形式后的总和长度大于 1,则继续将 integer 个值相加,直到得到 1 位数的总和。

我的代码问题是我预期的 output 对于值为 1 位的随机数已经会立即返回该数字,如果数字大于 1 的数字加起来是另一个大于 1 位的数字,它不会重复循环而是陷入无限循环。

let digitalRoot = (n) => {
  let stringNum = n.toString();
  let refArr = [];
  let result = 0;
  let iterator = refArr.values();

  while (stringNum.length > 1) {
    
    for (let i = 0; i < stringNum.length; i++) {
      let stringVal = stringNum[i];
      stringVal = parseInt(stringVal);
      refArr.push(stringVal)
    }
    
    for (let number of iterator) {
      if (result !== number) {
        result = result + number;
      }
      else {
        result = result + number;
      }
    }
    
    result = result.toString();
    if (result.length === 1) {
      result = parseInt(result);
      return result;
    }

    refArr = [];
    stringNum = result.toString();

  }

  if (stringNum.length === 1) {
    stringNum = parseInt(stringNum);
    return stringNum;
  }

}

例如1455的预期 output 应该是6 ,因为1 + 4 + 5 + 5 = 15 1 + 5 = 6

更新

我知道我在问题中的原始代码效率低下,但我能够通过编辑一些东西来获得预期的结果,首先是将 refArr 和迭代器变量移动到 while 循环中,将结果重置为 0 并进行一些其他修改。 显然我的代码是非常非常低效的解决方案,不推荐使用,但我想将我的代码作为练习等进行更正。

let digitalRoot = (n) => {
  let stringNum = n.toString();
  let result = 0;

  while (stringNum.length > 1) {
    let refArr = [];
    let iterator = refArr.values();

    for (let i = 0; i < stringNum.length; i++) {
      let stringVal = stringNum[i];
      stringVal = parseInt(stringVal);
      refArr.push(stringVal)
    }

    for (let number of iterator) {
      if (result !== number) {
        result = result + number;
      }
      else {
        result = result + number;
      }
    }

    let tester = result.toString();
    if (tester.length === 1) {
      tester = parseInt(tester);
      return tester;
    }

    stringNum = result.toString();
    result = 0;
    refArr = [];
  }

  if (stringNum.length === 1) {
    stringNum = parseInt(stringNum);
    return stringNum;
  }

}

你可以这样做...

 const digitalRoot = n => { while (n > 10) n = [...n.toString(10)].reduce((s,v)=>s + +v,0) return n } console.log( digitalRoot( 1455 ))

一些点...

.toString()
n.toString(10)12546更改为'12546'

传播语法 (...)
...'123456''12546'更改为'1','2','3','4','5','6' (迭代)
所以
[...'123456']创建一个数组 = [ '1','2','3','4','5','6' ]

数组.reduce()

+v字符串前的一元加号 (+)是:如文档中所写:
一元加号运算符 (+) 在其操作数之前并对其求值,但尝试将其转换为数字。

解释这里使用的reduce方法:
[ '1','2','3','4','5','6' ].reduce((s,v) => s + +v, 0)
做:

step 0  s =  0, v = '1' ->  0 + +'1' =  0 + 1 = 1 
step 1  s =  1, v = '2' ->  1 + +'2' =  1 + 2 = 3 
step 2  s =  3, v = '3' ->  3 + +'3' =  3 + 3 = 6 
step 3  s =  6, v = '4' ->  3 + +'4' =  6 + 4 = 10 
step 4  s = 10, v = '5' -> 10 + +'5' = 10 + 5 = 15 
step 5  return 15

如果 n 为负数会怎样? 为此,我们假设 n >= 0。 真的不清楚为什么你有 2 个循环,而第二个循环对某事进行了测试,但无论如何都做同样的事情。

  • 通常,尽量避免使同一个变量有时是数字有时是字符串。 "15" + 1 = "151"15 + 1 = 16
  • 在循环开始时重置累加器。
  • 很少需要在循环之前获取迭代器

简化版:

let digitalRoot = (n) => {
  while (n >= 10) {
    // convert to decimal
    let stringNum = n.toString();
    let result = 0
    for (let i = 0; i < stringNum.length; i++) {
      result +=  parseInt(stringNum[i]);
    }
    n = result
  }
  return n
}

更简单的方法是使用reduce() ,这个更高的 function 迭代一个值数组,并在每次迭代时减少这些值的数量,同时用数组中的下一个值计算累积的前一个值。

将字符串拆分为一个数组,然后 map 将其返回一个数字,并减少每次迭代时将累加器添加到返回值。

 const num = 1455; const num2 = 35714; const num3 = 11211; const sumUp = (num) => { return String(num).split('').map(Number).reduce((a, c) => a + c); } console.log(sumUp(num), sumUp(num2), sumUp(num3))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM