2

I'm trying to add all the elements of an array in which are embedded 3 other arrays of differing lengths. At the third level are two 1-element arrays whose values I cannot figure out how to access. What am I doing wrong? Please advise (no lamp-throwing, please).

function addArrayElems(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] === "number") sum += arr[i];
        for (var j = 0; j < arr.length; j++) {
            if (typeof arr[i][j] === "number") sum += arr[i][j];
        }
        //arr[i][j][k] doesn't work
        for (var k = 0; k < arr.length; k++) {
            if (typeof arr[i][j][k] === "number") sum += arr[i][j][k];
        }
        for (var l = 0; l < arr.length; l++) {
            if (typeof arr[i][j] === "number") sum += arr[i][j];
        }
    }
    return sum;
}
var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
console.log(addArrayElems(arr));
  • You need to place the second `for lus` inside the for lus `j`. Add this moment `arr[i][j][k]` will generated script error. Your are asking this `arr[i][undefined][undefined]`. You cannot retrieve a property from something that is undefined. – Mouser Jan 15 '15 at 16:32

6 Answers6

0

Let's use reduce!

function addArrayElems(arr) {
    return arr.reduce(function(memo, item){
        if (typeof item !== "number") {
            return memo + addArrayElems(item);
        }
        return memo + item;
    }, 0);
}
var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
console.log(addArrayElems(arr));
Victor
  • 9,210
  • 3
  • 26
  • 39
0

Explanation to the posted problem

function addArrayElems(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] === "number") sum += arr[i];
        for (var j = 0; j < arr.length; j++) {
            if (typeof arr[i][j] === "number") sum += arr[i][j];
            //added this line here. If arr[i][j] is defined and [i][j][0] return sum.
            if (arr[i][j] && typeof arr[i][j][0] === "number") sum += arr[i][j][0];
        }

        for (var l = 0; l < arr.length; l++) {
            if (typeof arr[i][j] === "number") sum += arr[i][j];
        }
    }
    return sum;
}
var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
console.log(addArrayElems(arr));

In your own code you iterated over the parent array arr. When you access arr[i] this will always work. JavaScript will return a value if set or else returns undefined. However when you try to access a property on an non-property (undefined) this will return a script error. You can't ask for the colour of an object that doesn't exist. The code above should return the desired results based upon the sample you've provided (Since the third level arrays are only 1 in length). The above example is just to explain how accessing values in multidimensional arrays work. However you want to do this recursively. I shall show you an example here below:

Improved answer (http://jsfiddle.net/o80e7f53/)

function addArrayElems(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] === "number") 
        {
            sum += parseInt(arr[i]); //parse number and add to sum.
        }
        else if (Object.prototype.toString.call(arr[i]) === '[object Array]')
        {
            sum += addArrayElems(arr[i]);
        }
    }
    return sum;
}
var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
console.log(addArrayElems(arr));

A recursive function calls itself again. Essentially if your multidimensional array is 100 arrays deep this function would still return all values. In your approach this should take 100 for loops you needed to write singlehandedly. This function loops over the values of an array and returns the sum when a number is found. If an array object is found the function call itself again except with the current array object. The returned result gets stored into sum. When the function finally returns to the first function call; sum contains all values from each array level.

Mouser
  • 13,132
  • 3
  • 28
  • 54
  • Yes, I couldn't figure out how to access the value when it was located in arr[6][5][0]. I like your use of inheritance in the else-if statement, btw, as well as the recursion. Thanks! – user3743226 Jan 15 '15 at 19:07
0

This should check for an array as you iterate through and then recursively sum them up. Note that this sample code expects integers.

  function getSumOfArray(arr) {
        var sum = 0;
        for (var i = 0; i < arr.length; i++) {
           //Check for array
           if( Object.prototype.toString.call( arr[i] ) === '[object Array]' ) {
              sum += getSumOfArray(arr[i]);
           } else {
              sum += parseInt(arr[i], 10);
           }
        }
        return sum;
    }
    
    var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
    
    alert(getSumOfArray(arr));
Paddy
  • 33,309
  • 15
  • 79
  • 114
  • This is very nice! I like the use of inheritance (Object.prototype.toString.call(...)) & the use of recursion. Thanks! – user3743226 Jan 15 '15 at 20:30
  • @user3743226 - not really inheritance, just a way of testing for array, borrowed from here: http://stackoverflow.com/questions/4775722/check-if-object-is-array – Paddy Jan 16 '15 at 09:11
  • OIC... Btw, the T.J. Crowder post is really interesting. Thanks a lot! – user3743226 Jan 17 '15 at 21:25
0

This is a prime candidate for recursion:

<script type="text/javascript">
    $(function () {
        var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
        var sum = sumArray(arr);
        alert(sum);
    });

    function sumArray(value) {
        var sum = 0;

        if (value == null) {
            return 0;
        }

        //Base Case
        if (typeof value == "number") {
            return value;
        }
        else
            //It must be an array
        {
            value.forEach(function (arrayItem) {
                sum += sumArray(arrayItem);
            });
        }
        return sum;
    }
</script>

EDIT

It was requested to solve this without JQuery. The function is still identical:

 <script type="text/javascript">
    function onClick() {
        var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];
        var sum = sumArray(arr);
        alert(sum);
    };

    function sumArray(value) {
        var sum = 0;

        if (value == null) {
            return 0;
        }

        //Base Case
        if (typeof value == "number") {
            return value;
        }
        else
            //It must be an array
        {
            value.forEach(function (arrayItem) {
                sum += sumArray(arrayItem);
            });
        }
        return sum;
    }
</script>

This function can be called however you like, for instance, I used an HTML Input without JQuery.

<input type="button" onClick="onClick()" value="Click ME"/>
TychonOmega
  • 116
  • 8
0

Another way to solve the problem:

 var arr = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];

// this functione merges all given arrays together and flattens the merged array.

 function merge_array(){

    var newArray = [];  
    var allArray = Array.prototype.concat.apply([],arguments);

    for(var e=0; e <allArray.length; e++){

       var ele = allArray[e];

       if(ele.__proto__.constructor === Array){
          newArray = newArray.concat(merge_array(ele));
       }
       else{
          newArray.push(ele);
       }

    }

    return newArray;

 }

// at the end just sum all number elements up:

 var singleArray = merge_array(arr);
 var sum = 0;
 for(var i=0; i<singleArray.length; i++){
   sum+=singleArray[i];
 }
 console.log('sum: ',sum);

Hope this helps.

Blauharley
  • 4,186
  • 6
  • 28
  • 47
  • You are building a whole new array just to solve this problem. Creating unnecessary loops (which won't work in browsers not supporting `Array.prototype.foreach`). Seams awfully elaborate and a bit of overkill for this situation. A tip: move the for loop into the function so the function returns the sum instead of having to add a for lus every time you want to have the sum. – Mouser Jan 15 '15 at 17:09
0

As of 2019 the answers using reduce are deprecated (or at least there is a better solution to solve it). Make use of the Array.flat() method to "flatten" the array and take the length of it:

var matrix = [1, 2, 3, 4, 5, [6, 7, 8, [9], [10]]];

// this will return you 10
console.log("Length of multidimensional array items: " matrix.flat().length) 
Sercan Samet Savran
  • 755
  • 1
  • 9
  • 20