4

I tried finding the sum of all numbers of a nested array, but I don't get it to work correctly. This is what I tried:

function arraySum(i) {
  sum = 0;
  for (a = 0; a < i.length; a++) {
    if (typeof i[a] == 'number') {
      sum += i[a];
    } else if (i[a] instanceof Array) {
      sum += arraySum(i[a]);
    }
  }
  return sum;
}

When you try it out with the array [[1,2,3],4,5], it gets 6 as the answer, instead of 15. Does somebody know where there is a mistake in it?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
user2846577
  • 43
  • 1
  • 1
  • 3

10 Answers10

9

The problem with your code is that the sum and a variables are global, instead of local. Because of this you get an infinite loop (a from the first entry in the function is reset by the second entry, so the same elements are processed again).

Fix it by adding var to where sum and a are declared to make them local to the function:

function arraySum(i) {
    var sum=0; // missing var added
    for(var a=0;a<i.length;a++){ // missing var added
        if(typeof i[a]=="number"){
            sum+=i[a];
        }else if(i[a] instanceof Array){
            sum+=arraySum(i[a]);
        }
    }
    return sum;
}

Demo: http://jsbin.com/eGaFOLA/2/edit

Tibos
  • 27,507
  • 4
  • 50
  • 64
  • +1, it seems everyone spotted the missing `var` for sum, but nobody noticed it missing in the for loop. Well done on the spot, and explaining the problem too! – musefan Oct 04 '13 at 12:57
4

I know it's late, but they say "is never late" :)

const sumNestedArray = arr => arr.flat(Infinity).reduce((a,b)=> a+b, 0)

const sumNestedArray = arr => arr.flat(Infinity).reduce((a,b)=> a+b, 0)

console.log(sumNestedArray([1,[2], [2, 3, [4]]]))
sumNestedArray([1,[2], [2, 3, [4]]])
Th1
  • 269
  • 2
  • 12
3

For 2018 this solution is clean and functional:

let arr = [[ 1, 2, 3], 4, 5]
arr.flat().reduce((d, i) => d + i)

Documentation for flat and reduce.

Santiago M. Quintero
  • 1,237
  • 15
  • 22
0

You're missing two var in there. You've implicitly declared sum and a at window scope:

function arraySum(i) {
    **var** sum=0;
    for(**var** a=0;a<i.length;a++){
        if(typeof i[a]=="number"){
            sum+=i[a];
        }else if(i[a] instanceof Array){
            sum+=arraySum(i[a]);
        }
    }
    return sum;
}
CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
0

Recurse, for example

function arraySum(x) {
    var sum = 0, i;
    if (typeof x === 'number')
        return x;
    else if (x instanceof Array)
        for (i = 0; i < x.length; ++i)
            sum += arraySum(x[i]);
    return sum;
}
arraySum([[1,2,3],4,5]); // 15

I didn't optimise this so that it's clear, you may want some more logic before recursion.


The reason yours isn't working is because you need to var both sum and a.

Paul S.
  • 64,864
  • 9
  • 122
  • 138
0

First of all why you use 'i' as input to function? we using 'i' to denote running index.. Regarding your question,you want 'a' to be local in your loop so instead of "for(a=0;..." instead write "for(var a=0;"

    <html>
    <body>
        <script>
            function NestedArraySummation(arr)
            {
                var sum=0;
                for(var i=0;i<arr.length;i++)
                {
                    if(typeof arr[i]=="number")
                    sum=sum+arr[i];
                    else  if(arr[i] instanceof Array)
                        sum=sum+NestedArraySummation(arr[i]);
                }
                    return sum;
            }

            var MyArray=[1,[2,3],4,10,[1,2]];
            var Sum=NestedArraySummation(MyArray);
            document.write(Sum);

        </script>
    </body>
</html>
Mendi Barel
  • 3,350
  • 1
  • 23
  • 24
0

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

const arr = [[1, 2, 3], 4, 5];
arraySum(arr);

function arraySum(arr) {
  var arrFlattens = _.flattenDeep(arr);
  // => [1, 2, 3, 4, 5]
  console.log(_.sum(arrFlattens));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
0

Here you go:

(My assumption is that you want to parse strings, e.g., '13', into numbers in order include them in the sum. If not, just change isNumber to typeof val === 'number'.

function arraySum(arr) {
  let sum = 0;

  while (arr.length) {
    const val = arr.pop();
    const isArray = typeof val === 'object' && val.length !== undefined;
    const isNumber = !isArray && !isNaN(sum + parseFloat(val)); 

    if (isArray && val.length) {
      sum += arraySum(val);
    }
    else if (isNumber) {
      sum += parseFloat(val);
    }
  }

  return sum;
}

console.log(arraySum([])); //0
console.log(arraySum([1, 1, 1, [3, 4, [8]], [4]])); //22
console.log(arraySum([1, 1, [], {}, 'l', 1, [3, 4, [8]], [4]])); //22
WesleyAC
  • 523
  • 6
  • 11
0

This was posted long ago but it might help others. I did the following and it seems to be working just fine

function countArray (array) {
 //iterate through the array
for(let i = 0;i < array.length; i++){
//check if element of array is an array, and if it is, run method flat() to the whole array. 
  if(Array.isArray(array[i])){
    array = array.flat()
  }
}
//return the sum of the elements of the array
 return array.reduce((a,b) => a + b);
    
}
Iglesfe
  • 1
  • 1
-1
from __builtin__ import int
def nestedLists(mylist):
    sum = 0
    if checkIfAllInt(mylist):
        result = addList(mylist)
        return result
    else:
        for value in mylist:
            sum = sum + nestedLists(value)
    return sum        

def addList(listdata):
    if(type(listdata) is int):
        return listdata
    else:
        return sum(listdata)    

def checkIfAllInt(listdata):
    check = True
    if(type(listdata) is int):
        return check
    else:
        for value in listdata:
            if(not type(value) is int):
                check = False
                return check
    return check    

print nestedLists([1,[2,3,[4,5,[6,7]]]])    
narendra-choudhary
  • 4,582
  • 4
  • 38
  • 58