递归计算嵌套数组的数量

Count Number of Nested Arrays Recursively

提问人:Sharon Kaufman 提问时间:12/21/2022 最后编辑:Sharon Kaufman 更新时间:12/21/2022 访问量:640

问:

我一直在试图弄清楚如何在 javascript 中递归计算嵌套数组的数量,但我似乎无法理解您将如何做到这一点。就像我知道我们需要在那里使用一个计数变量,我们需要能够访问元素,但是我们如何在每次看到新数组时计数呢?问题来了:给定一个嵌套数组,其中每个元素可能是 1) 整数或 2) 数组,其元素本身可能是整数或更多数组,计算数组的总数。

我已经尝试过了,在决定我们是否看到了一个新数组时,我不知道我在做什么。

`

function countArrays(array) {
  //counting the first array
    let sumTotal = 1;

    for(let element in array);
        if(Array.isArray(array))
            sumTotal += countArrays(array)
};

console.log(countArrays([1, 2, 3])) // 1
console.log(countArrays([1, [1, 2, 3], 3])) // 2

`

JavaScript 数组 计数 嵌套

评论


答:

3赞 Nina Scholz 12/21/2022 #1

您需要迭代项目,而不是数组/对象的键。

    for (let element of array)
                     ^^       ^

省略分号,因为这样可以防止下一个语句成为循环的一部分。它只是循环之后的下一个语句。

然后检查该元素是否为数组。

        if (Array.isArray(element))

以及使用此项的递归调用的结果。

最后返回计数。

    return sumTotal;

如果未找到 return 语句,则函数将返回 allways undefined

function countArrays(array) {
    let sumTotal = 1;

    for (let element of array)
        if (Array.isArray(element))
            sumTotal += countArrays(element);

    return sumTotal;
}

console.log(countArrays([1, 2, 3])) // 1
console.log(countArrays([1, [1, 2, 3], 3])) // 2

也许用 block 语句包装所有循环和条件语句更容易获得应用范围的视觉反馈。

function countArrays(array) {
    let sumTotal = 1;

    for (let element of array) {
        if (Array.isArray(element)) {
            sumTotal += countArrays(element);
        }
    }

    return sumTotal;
}

console.log(countArrays([1, 2, 3])) // 1
console.log(countArrays([1, [1, 2, 3], 3])) // 2

评论

0赞 Sharon Kaufman 12/21/2022
谢谢妮娜!现在更有意义了。我刚刚开始学习递归,我很难掌握整个想法。再次感谢!!
0赞 Sharon Kaufman 12/21/2022
你能向我解释一下递归行在做什么吗?如何剖析 sumTotal += countArrays(element)
0赞 Nina Scholz 12/21/2022
此行采用数组元素(即数组)调用函数的结果,并将结果分配给 的实际值。countArraysumTotal
0赞 Sharon Kaufman 12/21/2022
好的,那么这也是使代码继续运行以迭代到下一个元素等等的原因吗?
0赞 Nina Scholz 12/21/2022
是的。它使用不同的参数调用函数,直到所有嵌套调用都未完成,调用函数将等待结果。
0赞 benji 12/21/2022 #2

另一种方法可以做到这一点,如果你对何时使用 of 或 in 循环感到困惑,只需使用一个普通的旧 for 循环。我们可以通过获取数组的长度并遍历并查找数组中的索引是否确实是数组来做到这一点。

function countArray(arr) {
    let count = 1;
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
           count++;
        }
    }
    return count;
} 

评论

0赞 Sharon Kaufman 12/21/2022
啊,是的,谢谢本吉!不过,我确实需要使用递归解决方案来解决这个问题,当调用它添加到 count 变量时,我并不真正理解它在做什么。
0赞 Scott Sauyet 12/21/2022
countArray ([1, [2], 3, [4, 5, [6, 7], 8, [9, 10, [[[11]]]]]]) //=> 3/ 大概应该是 .8
1赞 Scott Sauyet 12/21/2022 #3

妮娜的回答很棒。它解释了你做错了什么以及如何解决它。

但是,如果你正在寻找一个更简单的递归版本,你可以尝试如下方法:

const countArrays = (xs) =>
  Array .isArray (xs)
    ? 1 + xs .map (countArrays) .reduce ((a, b) => a + b, 0)
    : 0

console .log (countArrays ([1, [2], 3, [4, 5, [6, 7], 8, [9, 10, [[[11, 12]]]]]]))

但我更愿意提取 helper 函数,并像这样写:sum

const sum = ([x, ...xs]) =>
  x == undefined ? 0 : x + sum (xs)

const countArrays = (xs) =>
  Array .isArray (xs)
    ? 1 + sum (xs .map (countArrays))
    : 0

console .log (countArrays ([1, [2], 3, [4, 5, [6, 7], 8, [9, 10, [[[11, 12]]]]]]))

(通常我会使用更有效的 来编写,但由于您正在研究递归,因此查看递归版本也可能很有用。sumreduce