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

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

我正在编写一个程序,该程序将任意随机整数相加并得出一个总和。如果转换为字符串形式的和的长度大于 1,我们继续将整数值加在一起的过程,直到我们达到 1 位的和。

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

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 的预期输出应该是 6,因为 1 + 4 + 5 + 5 = 15; 1 + 5 = 6

更新

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

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;
  }

}

如果 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
}

你可以做到...

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'

spread syntax (...)
...'123456''12546' 更改为 '1','2','3','4','5','6'(迭代)
所以
[...'123456'] 创建数组 = [ '1','2','3','4','5','6' ]

Array.reduce()

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

解释这里使用的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

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

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

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))