5

Let's say I have this:

function arrSum(){
  *code here*
}

How do I write the arrSum function such that it can sum all the integers within a multidimensional array (of variable depth).

I.e.

arrSum([2, 5, [4, 6], 5]) === 22;

I know there must be an answer to this somewhere but I really can't find it. If this is a duplicate please let me know.

1
  • 1
    There is an anwser but using ES6: stackoverflow.com/a/33306533/5388620 It's almost the same answer as below and uses recursion too. Commented Nov 12, 2015 at 6:08

9 Answers 9

8

Simply you can write a function like this with recursion

function arrSum(arr) {
  var sum = 0;
  // iterate array using forEach, better to use for loop since it have higher performance
  arr.forEach(function(v) {
    // checking array element is an array
    if (typeof v == 'object')
      // if array then getting sum it's element (recursion)
      sum += arrSum(v);
    else
      // else adding the value with sum
      sum += v
  })
  // returning the result
  return sum;
}

console.log(arrSum([2, 5, [4, 6], 5]) === 22);

Using for loop

function arrSum(arr) {
  var sum = 0;
  for (var i = 0; i < arr.length; i++) {
    if (typeof arr[i] == 'object')
      sum += arrSum(arr[i]);
    else
      sum += arr[i];
  }
  return sum;
}

console.log(arrSum([2, 5, [4, 6], 5]) === 22);

Sign up to request clarification or add additional context in comments.

5 Comments

This works perfectly - thank you. Can I just ask - why are you testing for typeof object?
@VoA : checking inner element is array or number, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
I would just move the isObject check before the foreach, that way, sending a single numeric, it will still work.
In your for loop answer you wrote: "sum += arrSum(arr[i]);". Could you explain what this is doing? Is it calling the arrSum function from within itself?
@VoA : calling the same function with inner array ( recursion ), and adding return value with sum variable
5

A more modern approach using .reduce():

const arr = [2, 5, [4, 6], 5];

const arrSum = array =>
    array.reduce(
        (sum, num) => sum + (Array.isArray(num) ? arrSum(num) : num * 1),
        0
    );

console.log(arrSum(arr));

Comments

5

Why is no one using flat()?

const arr = [2, 5, [4, 6], 5];

const result = arr.flat().reduce((a,b) => a+b);

console.log(result);

Comments

1

Check this:

function arrSum(objArr){
  var total = 0;
  for(var outerLoop=0; outerLoop < objArr.length; outerLoop++){
    if(objArr[outerLoop].constructor === Array){
      for(var innerLoop=0; innerLoop < objArr[outerLoop].length; innerLoop++){
        total += objArr[outerLoop][innerLoop];
      }
    } else {
      total += objArr[outerLoop];
    }
  }
  return total;
}

alert (arrSum([2, 5, [4, 6], 5]));

1 Comment

OP said of variable array depth. This will only go two deep.
1
    function arrSum(arr) {
        var totalSum = null;
        var numString = arr.toString();
        var numberArray = numString.split(",");
        numberArray.forEach(function(ele){
          totalSum = totalSum + parseInt(ele);
        });
        return totalSum;
    }
    console.log(arrSum([2, 5, [4, 6], 5]);

Comments

1

If we have a multi-dimensional array with strings and integers and we have to get the sum of the numbers, then following @Pranav C Balan's solution we could add a check in the else loop to check only for digits as below -

      function arrSum(arr) {
		  var sum = 0;
		  for (var i = 0; i < arr.length; i++) {
			   if (typeof arr[i] == 'object'){
			      sum += arrSum(arr[i]);
			   }else if (Number(arr[i])){
			      sum += arr[i];
			   }
		  }
		  return sum;
		}
		console.log(arrSum([2, 'a', 5, [4, 6, 10, [1, 2, 'b'], 10], 5]));

Comments

0

I would build a function similar to what Pranav C Balan with the difference that i would check the isObject() before calling forEach(),
This way i get around problems posed by sending a single numeric parameter, or Null values.

function arrSum(v) {
  // checking if element is an array
  if (typeof v == 'object') {
    var sum = 0;
    
    // iterate array using forEach, better to use for loop since it have higher performance
    v.forEach(function(e) {
      sum+=arrSum(e);
    });
    return sum;
  }
  else {
      return v;
  }
}
$('body').append($('<p></p>').html('[2, 5, [4, 6], 5] = ' + arrSum([2, 5, [4, 6], 5])));
$('body').append($('<p></p>').html('[2,, 5] = ' + arrSum([2,, 5])));
$('body').append($('<p></p>').html('5 = ' + arrSum(5)));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Comments

0

This can be done with lodash _.flattenDeep and _.sum:

var arr = [2, 5, [4, 6], 5];
arrSum(arr);

function arrSum(arr) {
  var arrFlattens = _.flattenDeep(arr);
  // => [2, 5, 4, 6, 5]
  console.log(_.sum(arrFlattens));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Comments

0

Expanding on @zeh's answer to include a check for number and convert a string to a number:

function arrSum(arr) {
  const sum = arr.flat().map(a => +a).filter(a => typeof a === "number" && !isNaN(a)).reduce((a,b) => a + b, 0);
  return sum;
}

Below is a breakdown of the code using an example 3D array - flat() depth set to 2.

const array3d  = [[2, '8', 5], [[4, 6], 10],[1, 2, 'b'],[10, 5, 'f']];

function arrSumBreakdown(arr) {
  // change any number strings to numbers
  const allnum   = arr.flat(2).map(a => +a);
  console.log('flat & convert to numbers: ',...allnum);
  // keep only numbers and remove NaN
  const numonly  = allnum.filter(a => typeof a === "number" && !isNaN(a));
  console.log('remove NaN:',...numonly);
  // sum array
  const sumnum   = numonly.reduce((a,b) => a + b, 0);
  return sumnum;
}

console.log('sum array:',arrSumBreakdown(array3d));

// all in one
function arrSum(arr) {
  const sum = arr.flat(2).map(a => +a).filter(a => typeof a === "number" && !isNaN(a)).reduce((a,b) => a + b, 0);
  return sum;
}

console.log('combine all elements (sum array):',arrSum(array3d));

references:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.