【问题标题】:How to add up numbers in a nested array javascript如何将嵌套数组中的数字相加javascript
【发布时间】:2016-02-26 05:48:05
【问题描述】:

刚刚从事一个项目并尝试了几种不同的解决方案,但都没有结果。有人可以帮助我如何将嵌套数组中的数字相加吗?我会使用减少吗?还是for循环?

function balance(arr) {
  if(typeof item == 'number') {
    return arr;enter code here
  } else {
    return arr + balance(item);
  }
}

【问题讨论】:

  • 显示你的数组和你尝试的代码
  • 递归减少,通过它的声音。 任何您尝试的解决方案没有结果
  • reduce 可以帮助模块化代码,但 for 循环可能更快(而且代码不多)。尽可能避免递归,它很慢。
  • @RobG:除非知道嵌套的深度,否则这里没有办法避免递归,不是吗?除非知道我们正在处理不合理的数据量,否则我不会为了执行速度而牺牲可读性。
  • @ArnoldB 我想你可能遗漏了一个 reduce 函数和数组

标签: javascript logic


【解决方案1】:

这可能是你所希望的吗?

function balance(arr) {
  return arr.reduce(function(sum, item) {
    if(typeof item == 'number') {
      return sum;
    } else {
      return sum + balance(item);
    }
  },0);
}

console.log(balance([1,2,[3,4],5]));

【讨论】:

  • 这行不通,在return sum;这一行之前需要sum += item
【解决方案2】:

只是为了记录(为了反驳需要递归的断言),这是一个使用顺序算法的版本。递归简洁且(通常)更易于阅读,但是如果速度很重要,它可能会很慢。然而,根据jsPerf 的结果,脚本引擎在优化递归代码方面似乎比以前好得多,至少对于像这样的简单程序是这样。

为了比较,我包含了一个使用普通循环的递归版本,jsPerf 测试还包括一个使用 reduce 的(固定)递归版本。我怀疑 Any 的回答会最慢,因为它在每个循环中调用 slice 和自身,但我没有时间修复它。

所以我想递归在这里很好,因为它既快速又简洁。

/*  Sum the values of nested arrays. Only checks if values are arrays,
**  otherwise assumes they're numbers
**
**  @param {Array} arr - array of numbers to process, may have 
**                       nested arrays of numbers
**  @returns {number} - sum of values or NaN if arr is not an Array
*/
function balance(arr) {
  
  // Only process arrays
  var isArray = Array.isArray;
  if (!isArray(arr)) return NaN;

  // Setup
  var arrays = [], indexes = [];
  var currentArray = arr;
  var currentValue;
  var sum = 0;
  var i = 0, iLen = arr.length;
  
  // Use <= length as must handle end of array inside loop
  while (i <= iLen || arrays.length) {
    currentValue = currentArray[i];

    // If at end of current array, reset value to before entering array
    // Reset i to previous value as will increment at the bottom
    if (i == currentArray.length && arrays.length) {
      currentArray = arrays.pop();
      i = indexes.pop();
      iLen = currentArray.length;

    // If current value is an array, use it and reset loop control values
    // set i to -1 as will increment at the bottom
    } else if (isArray(currentValue)) {
      arrays.push(currentArray);
      indexes.push(i);
      currentArray = currentValue;
      i = -1;
      iLen = currentArray.length;

    // Otherwise, add the current value
    // Will be undefined if at end of array so add zero
    } else {
      sum += +currentValue || 0;
    }
    
    // Increment i
    i++;
  }
  return sum;
}

document.write(
  'balance sequential 1: ' +
  balance([1,[2,1,[1,2,-1],[1]],1,[2,1]]) // 11
  + '<br>balance sequential 2: ' +
  balance([1,2,[3,4],5]) // 15
);


/*  Sum the values of nested arrays. Only checks if values are arrays,
**  otherwise assumes they're numbers
**
**  @param {Array} arr - array of numbers to process, may have 
**                       nested arrays of numbers
**  @returns {number} - sum of values or NaN if arr is not an Array
*/
function balanceLoop(arr) {
  if (!Array.isArray(arr)) return NaN;
  for (var value, total=0, i=0, iLen=arr.length; i<iLen; i++) {
    value = arr[i];
    total += Array.isArray(value)? balanceLoop(value) : value;
  }
  return total;
}

document.write(
  '<br>balanceLoop 1: ' +
  balanceLoop([1,[2,1,[1,2,-1],[1]],1,[2,1]]) // 11
  + '<br>balanceLoop 2: ' +
  balanceLoop([1,2,[3,4],5]) // 15
);

【讨论】:

    【解决方案3】:

    一个简单的递归函数:

    function balance(arr, total) {
      total = total || 0;
      if (arr.length === 0) return total;
      var head = arr[0];
      if (typeof head === 'number') {
        return balance(arr.slice(1), total += head);
      } else {
        return balance(head, total);
      }
    }
    
    balance([1, [2, 1, 3, [43, 2]]])); // 52
    

    DEMO

    【讨论】:

    • 不适用于像 [1,[2],1] 这样嵌套的数组,它返回 3 而不是 4。在数组的每个成员上调用自身而不是仅在遇到新的数组成员。
    • :) 我正要评论你在评论中不必要的好斗,但现在我不必这样做了。感谢您发现错误,并为我指明了正确的方向。递归仍然给我带来了一些问题,但我最终会到达那里。
    • 在不过度使用表情符号或过于谨慎(这本身可能很烦人)的情况下,确保书面交流保持友好是一项挑战。请接受 cmets 的意思,而不是争论。 :-)
    【解决方案4】:

    我可能会通过以下方式使用递归减少来解决这个问题:

    function balance(arr) {
      return arr.reduce(function(sum,item) { 
        return sum + (item instanceof Array ? balance(item) : item);
      }, 0); 
    };
    
    balance([1,[2,1,[1,2,-1],[1]],1,[2,1]]); // 11
    

    如果您不介意开销,您当然可以这样做:

    Number.prototype.balance = function() { return this; };
    Array.prototype.balance = function() { return this.reduce(function(a,b) { return a + b.balance(); }, 0); }
    
    [1,[2,1,[1,2,-1],[1]],1,[2,1]].balance(); // 11
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-06
      • 2019-02-11
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2018-02-04
      相关资源
      最近更新 更多