【问题标题】:Javascript unlimited nested array handlingJavascript无限嵌套数组处理
【发布时间】:2013-10-11 14:25:43
【问题描述】:

我正在尝试和解决 8m 7s 中提到的问题的朋友一起玩,而对我来说,它已经走了 20m。我不知道如何在 javascript 中处理无限的嵌套数组。

问题是这样的:

// i will be an array, containing integers, strings and/or arrays like itself.
// Sum all the integers you find, anywhere in the nest of arrays.

所以

arraySum([[1,2,false],'4','5']) will return 3 (passed)
arraySum([[1,2,3],4,5]) will return 15 (passed)
arraySum([[[[[[[[[1]]]]]]]], 1]) will return 2 (failed)

我写的代码是:

function arraySum(i) {

sum = 0;
tmp =0;
for (var a=0; a<i.length; a++){
    if (i[a] instanceof Array) {
        ar = i[a];
        for (var j=0; j<ar.length; j++){
            tmp +=ar[j];
        }
    }
    if (typeof i[a] == "number")
        sum += i[a];
        console.log(sum);
}
return sum + tmp;

}

如您所见,它无法处理我失败的最后一种情况,因为我无法弄清楚如何在 JS 中处理无限嵌套。

任何想法将不胜感激。 也尽量在 8m 7s 之前完成,我的伙伴完成了。

【问题讨论】:

  • if (i[a] instanceof Array) { 部分中,您必须使用递归,而不仅仅是嵌套循环

标签: javascript algorithm recursion nested multidimensional-array


【解决方案1】:

if (i[a] instanceof Array) { 部分内部,您必须使用递归来操作具有相同arraySum 函数的嵌套数组,而不仅仅是使用另一个循环。试试这个:

var arraySum = (function () {
    "use strict";

    var sumFunc, isArray;

    sumFunc = function (arr) {
        var sum, i, j, cur, toAdd;

        sum = 0;

        for (i = 0, j = arr.length; i < j; i++) {
            cur = arr[i];

            toAdd = 0;
            if (isArray(cur)) {
                toAdd = sumFunc(cur);
            } else if (typeof cur === "number") {
                toAdd = cur;
            }

            sum += toAdd;
        }

        return sum;
    };

    isArray = Array.isArray || function (obj) {
        return Object.prototype.toString.call(obj) === "[object Array]";
    };

    return sumFunc;
}());

演示: http://jsfiddle.net/Q7JPM/1

该函数只是遍历数组中的所有项目,并返回其中找到的任何数字的总和。如果项目本身是一个数组,它会调用arraySum 并传递该数组...将结果添加到总和中。如果它是一个数字,它只是将它添加到总和中。

【讨论】:

  • @shash7 谢谢,我真的很感激 :) 你的评论让我回到了这里,并让我想起了自从我发布这个答案以来我想改变的一些事情,所以我继续做了!希望它们是积极的变化
  • 如果您有嵌套对象的键引用其他对象集合(..考虑组织图和层次结构),您能否发布解决方案。前任。 {id: #, children: {collection}},在很多级别。因为我正在努力并且在第二次递归调用中丢失了集合引用。好贴。谢谢。
【解决方案2】:

你必须使用递归:

http://jsfiddle.net/HMnat/2

function arraySumRec(theArray)
{
    var sum=0;
    for (var i=0;i<theArray.length;i++)
    {
        if (theArray[i] instanceof Array)
        {
            sum=sum+arraySumRec(theArray[i]);
        }
        else
        {
            if (typeof(theArray[i])=="number")
                {
                 sum=sum+theArray[i];
                }
        }
    }
      return sum;
}

花了我 3 分 47 秒(由于错字,哈哈)。

【讨论】:

  • 啊。我提到的那个“错字”大概是有人对我投反对票的原因——我没有保存正确的 jsFiddle!我已经更新到我想要链接到的正确 jsfiddle。顺便说一句,如果反对者可以留下某种评论,例如“您的解决方案不起作用”,那就太好了。
【解决方案3】:

Javascript Array reduce 方法非常适合解决此类问题。 reduce 方法接受一个至少有两个参数的函数:累加器和数组的当前元素。在函数体中,您指定每个元素应如何影响累加器。函数的第二个参数是累加器的起始值。

function sum(x) {
  return x.reduce(function(accumulator, currentValue) {
    if (typeof currentValue === "number") {
      return accumulator + currentValue;
    } else if (currentValue instanceof Array) {
      return accumulator + sum(currentValue);
    } else {
      return accumulator;
    }
  }, 0);
}

JSFIDDLE

函数 sum 接受一个数组,reduce 方法将其缩减为单个值。在“else if”分支中,我们找到一个嵌套数组,我们可以简单地对其调用 sum,返回一个值,并将其添加到我们的累加器中。在“else”分支中,我们没有找到我们感兴趣的值类型,所以我们保持累加器不变。

documentation at MDN 通过示例很好地解释了 Array reduce。

【讨论】:

    【解决方案4】:
    function arraySum(i) {
            var l = i.length, sum = 0;
            while (l--) { 
                if (typeof i[l] !== 'number' && !(i[l] instanceof Array)) continue;
                if (i[l] instanceof Array) { sum += arraySum(i[l]); continue; }
                sum += i[l];
            }
            return sum;
    }
    

    【讨论】:

      【解决方案5】:

      使用堆栈的非递归。

              function arraySum(arr) 
              {
                  var sum = 0;   
      
                  while(arr.length != 0)
                  {
                     var value = arr.pop();
                     if(value instanceof Array)
                     {
                       for (i= 0; i< value.length; ++i) 
                         arr.push(value[i]);
                     }
                     else if(typeof value === "number")
                      sum += value;
                   }
      
                   return sum;
              }
      
              var arr = [1, 2, [3, 4, [[[5]]]]];
              console.log(arraySum(arr));
      

      【讨论】:

        【解决方案6】:

        如果我们专注于正确的部分,我们就可以避免专注于错误的部分——

        function arraySum (t)
        { switch (t?.constructor)
          { case Array:
              return t.reduce((r, v) => r + arraySum(v), 0)
            case Number:
              return t
            default:
              return 0
          }
        }
        
        console.log(arraySum([[1,2,false],'4','5']))
        console.log(arraySum([[1,2,3],4,5]))
        console.log(arraySum([[[[[[[[[1]]]]]]]], 1]))
        3
        15
        2
        

        如果您的环境尚不支持?.,您可以将其换掉 -

        switch (t?.constructor)
        switch (t && t.constructor) // <- where ?. is unsupported

        编辑:我花了 2,769 天来回答这个问题,但只用了几分钟来写:D

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-15
          • 2020-05-19
          • 1970-01-01
          • 1970-01-01
          • 2018-06-24
          • 1970-01-01
          • 2018-02-04
          • 1970-01-01
          相关资源
          最近更新 更多