JavaScript 错误:即使 typeof 函数返回“数字”,函数也返回 NaN

时间:2021-06-01 14:43:33

标签: javascript ecmascript-6 ecmascript-5

我想找到由给定数的排列产生的最大数。

如果给定的数字是 123,那么它排列的最大数字是 321。

编辑

我通过改变取得了一些进步

if (str.length === 0) return "";
if (str.length === 1) return str;

if (str.length === 0) {
    return "";
} else {
    return str;
}

然而,仍然存在一个问题:该函数返回一个字符串。实际上,数组成员是字符串而不是数字

function findPerms(num) {
    var str = num.toString();
    
  if (str.length === 0) {
        return "";
    } else {
        return str;
    }
 
  let result = [];
  for (let i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    for (let j = 0; j < remainingChars.length; j++) {
      result.push(Number(currentChar + findPerms(remainingChars)[j]));
    }
  }

    result.sort(function(a, b) {
        return a - b;
    });

  return result[result.length - 1];
    
}


console.log(findPerms(11121));
console.log(typeof findPerms(11121));

为此我做了:

function findPerms(num) {
  var str = num.toString();

  if (str.length === 0) return "";
  if (str.length === 1) return str;
  let result = [];
  for (let i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    for (let j = 0; j < remainingChars.length; j++) {
      result.push(Number(currentChar + findPerms(remainingChars)[j]));
    }
  }

  result.sort(function(a, b) {
    return a - b;
  });

  return result[result.length - 1];

}

console.log(findPerms(11121));
console.log(typeof findPerms(11121));

问题

我一定犯了一个我无法发现的错误,因为上面的函数返回 NaN(即使 typeof findPerms(11121) 返回“数字”)。

我的错误在哪里?

2 个答案:

答案 0 :(得分:0)

编辑
我想这就是你想做的。
使用递归制作一个数字的所有数字排列的数组。
对数组进行排序。
返回数字最大的排列。

这可以通过将问题分解为两个函数来完成。
第一个函数返回一个数字所有排列的数组。
第二个函数从第一个函数中获取数组结果,然后对其进行排序。然后它返回最后一个值。
您的递归运行不正常。这就是它不起作用的原因。

<html><head><title>6770990</title>
<script>
function findPerms(num) {
  var str = num.toString(); var result = [];
  if (str.length == 0) return result;
  if (str.length == 1) return [parseInt(str)];
  for (var i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1)
    var perms = findPerms(remainingChars) //----Permutation array of remaining chars.
    for (var j = 0; j < perms.length; j++) {
      result.push(parseInt("" + currentChar + perms[j]));
    }
  }
  return result; //----All permutations for num.
}
function findLargestPerm(num)
{ var perms = findPerms(num); perms.sort(function(a,b) {return a-b;});
  return perms[perms.length-1];
}
</script>
</head></body>
<script>
var r = findLargestPerm(11121); alert("r=" + r);
</script>
</body></html>

上一个回答

以相反的顺序对数字进行排序并连接成一个数字会更有效。这将是最大的排列。

函数 findPerms() 试图找到一组数字的最大排列。有时,将函数重命名为它的作用会有所帮助,以便更容易遵循逻辑。

再次使用递归调用函数的行只需要为每个当前字符调用一次。

以下代码显示了发生的步骤。

<html><head><title>6770990</title>
<script>
var msg="";
function findLargestPermutation(num)
{ var str = num.toString(); msg += "findLargestPermutation(" + str + ")<br>";
  if (str.length === 0) return "";
  if (str.length === 1) return str;
  let result = [];
  for (let i = 0; i < str.length; i++)
  { const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    msg += "currentChar=" + currentChar + " remainingChars=" + remainingChars + "<br>";
    //----The j loop should be removed and just use this line.
    var num = Number(currentChar + findLargestPermutation(remainingChars));
    msg += "num=" + num + "<br>";
    result.push(num);
  }
  result.sort(function(a, b) {return a - b;});
  msg += "findLargestPermutation()=" + result[result.length - 1] + "<br>";
  return result[result.length - 1];
}
</script>
</head><body>
<div id="div"></div>
<script>
var lp = findLargestPermutation(11121);
alert("lp=" + lp + " typeof lp=" + typeof lp);
document.getElementById("div").innerHTML = msg;
</script>
</body></html>

答案 1 :(得分:0)

您的代码存在一些问题,但让我们先尝试正确定义需求。 如果我明白你想要做的是找到一个数字的所有排列并选择数字中数字的最高排列。 你想要做的是这样的:

  1. 创建一个空列表
  2. 遍历初始号码的数字。
  3. 对于每个数字循环遍历剩余的数字并找到所有可能的组合并将它们添加到初始空列表中。
  4. 在列表中获得所有可能的数字组合后,对它们进行排序并返回最高的结果。

这里有两个问题,首先是代码执行中存在一些错误,并且您的算法效率不高。 让我们解决第一个: 当您创建结果列表时,您在递归函数中定义它,这意味着它会在每次递归调用时被一个空数组覆盖。通常,当您应用此技术时,您要么在递归函数之外定义结果数组,要么将其作为参数传递,以便能够对结果进行迭代。 你似乎没有很好地理解函数作用域和闭包在 JS 中是如何工作的。为此,我建议您阅读 MDN 上的一些资源。

这里的另一个问题是您希望该函数接收一个数字作为参数,但是当您调用它时

result.push(Number(currentChar + findPerms(remainingChars)

remainingChars 是一个字符串,因此结果为 NaN。

现在进入第二个问题。考虑到您希望从一系列数字中获得尽可能高的数字,您可以将数字从最高到最小排序,然后提供结果。 例如: 如果数字是 18,您可以将其按 [8, 1] 之类的数组进行排序,然后将其连接到 81。 代码可能看起来像:

function findHighestPerm(no) {
  const arr = no.toString().split('');
  return parseInt(arr.sort((a, b) => b - a).join(''));
}

PS:我知道我的代码不是最有效或最优雅的,但我只是懒惰,它可以工作;)