简体   繁体   中英

How to add up numbers in a nested array javascript

Just working on a project and tried a few different solutions but with no results. Could someone help me with how to add up numbers in a nested array? Would I use reduce? or a for loop?

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

Is this maybe what you are hoping for?

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

Just for the record (to disprove the assertion that recursion is required), here's a version that uses a sequential algorithm. Recursion is concise and (usually) easier to read, however if speed matters, it can be slow. However, based on results from jsPerf , script engines seem very much better at optimising recursive code than they used to be, at least for simple programs like this.

For comparison, I've included a recursive version using a plain loop, the jsPerf tests also include a (fixed) recursive version using reduce . I suspect Any's answer will be slowest as it calls slice and itself on every loop, but I didn't have time to fix it.

So I guess recursion is fine here as it is fast and concise.

 /* 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 ); 

A simple recursive function:

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

I would probably solve this using a recursive reduce, in the following manner:

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

If you don't mind the overhead, you could of course do this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM