TheNovice
TheNovice

Reputation: 1287

Sum two arrays in single iteration

I want to sum each value of an array of numbers with its corresponding value in a different array of numbers, and I want to do this without looping through each individual value.

So:

var array1 = [1,2,3,4];
var array2 = [5,6,7,8];

var sum    = [6,8,10,12];

I'd love to do it in one fell swoop, instead of doing this:

for(var i = 0; i < array1.length; i++){
   sum.push(array1[i] + array2[i]);
}

Can anyone think of a way? I'm pretty stumped.

Upvotes: 65

Views: 164154

Answers (17)

Ajit Shaw
Ajit Shaw

Reputation: 44

If you have two arrays with different lengths then here is how you can sum them up.

<pre>
    var array1 = [1,2,3,4,9];
    var array2 = [5,6,7,8];

    sum = [6,8,10,12,9];
</pre>

We can start a new loop and then check if the index exists in the array if not then assign it to 0.

Map

<pre>
    const output = [];

    array1.map((item, i) => {
        output.push((array1[i] ? array1[i] : 0) + (array2[i] ? array2[i] : 0)); 
    });

    console.log(output) // [ 6, 8, 10, 12, 9 ]
</pre>

Reduce

<pre>
    let output = array1.reduce((newArray, item, i) => {
        newArray.push((array1[i] ? array1[i] : 0) + (array2[i] ? array2[i] : 0));
        return newArray;
    }, []);
    console.log(output); // [ 6, 8, 10, 12, 9 ]
</pre>

Upvotes: -1

3limin4t0r
3limin4t0r

Reputation: 21130

Note: This answer does NOT solve the issue in a single iteration.

Base Case Solution

You can split this issue into two separate issues.

  1. First we need to combine the elements of elements of the different arrays that are present on the same index. This is commonly called "zipping arrays". You'll find a zip() methods in a lot of libraries, but can easily create your own.

    const array1 = [1,2,3,4];
    const array2 = [5,6,7,8];
    
    zip(array1, array2) //=> [ [1,5], [2,6], [3,7], [4,7] ]
    

    If you aren't using a library that has this included, you must define your own. A simple variant looks like this:

    function zip(...arrays) {
      const length = Math.max(...arrays.map(array => array.length));
      return Array.from({ length }, (_, i) => arrays.map(array => array[i]));
    }
    
  2. Now that we have combined the two arrays, we need to sum each of the nested arrays. For this we must first know how to sum values in a normal array.

    Just like zipping arrays, summing them is such a common action that most libraries provide a helper. Check any libraries you're using before defining your own sum().

    A normal array of numbers can produce a sum by using reduce().

    numbers.reduce((sum, number) => sum + number, 0);
    

    It's probably a good idea to store this in a new function definition. sum(numbers) is far more descriptive than the numbers.reduce(...) line.

    function sum(numbers) {
      return numbers.reduce((sum, number) => sum + number, 0);
    }
    

We now have all the building blocks to produce the desired result.

const result = zip(array1, array2).map(numbers => sum(numbers));
//=> [6, 8, 10, 12]

// simplified
const result = zip(array1, array2).map(sum);
//=> [6, 8, 10, 12]

The above combines array1 and array2 like shown in 1. Then we map() each of the resulting pairs to their sum.

const array1 = [1,2,3,4];
const array2 = [5,6,7,8];

const result = zip(array1, array2).map(sum);
console.log(result);

// helpers
function zip(...arrays) {
  const length = Math.max(...arrays.map(array => array.length));
  return Array.from({ length }, (_, i) => arrays.map(array => array[i]));
}

function sum(numbers) {
  return numbers.reduce((sum, number) => sum + number, 0);
}

More Arrays

This solution allows you to easily change the number of arrays.

const result = zip(array1, array2, array3, array4).map(sum);

Non-Matching Array Lengths

Do note that it's expected that all the arrays do have the same length. If the length doesn't match the sum will result in NaN, since number + undefined = NaN

zip([1,2,3], [4,5], [6])
//=> [ [1,4,6], [2,5,undefined], [3,undefined,undefined] ]

To solve this you could add another helper to remove "empty" values. For this we can introduce the compact() helper, which removes null and undefined values from the array.

function compact(array) {
  return array.filter(item => item != null); // removes both `null` and `undefined`
}

Here is an example usage:

zip([1,2,3], [4,5], [6]) // [ [1,4,6], [2,5, undefined], [3,undefined,undefined] ]
  .map(compact)          // [ [1,4,6], [2,5], [3] ]
  .map(sum)              // [ 11, 7, 3 ]

const array1 = [1,2,3];
const array2 = [4,5];
const array3 = [6];

const result = zip(array1, array2, array3).map(compact).map(sum);
console.log(result);

// helpers
function zip(...arrays) {
  const length = Math.max(...arrays.map(array => array.length));
  return Array.from({ length }, (_, i) => arrays.map(array => array[i]));
}

function sum(numbers) {
  return numbers.reduce((sum, number) => sum + number, 0);
}

function compact(array) {
  return array.filter(item => item != null);
}

Upvotes: 0

Abu Sufyan
Abu Sufyan

Reputation: 1

let array1=[];
let array2=[];
let array3=[];
let sum=0;

// Take elements from the user for 1st Array

for(let i=0; i<3; i++){
    array1[i]=Number(prompt(i));
}
console.log(array1);

// Take elements from the user for 2nd Array

for(let j=0; j<3; j++){
    array2[j]=Number(prompt(j));
}
console.log(array2);

// add sum of two arrays in 3rd Array

for(k=0; k<3; k++){
    sum=(array1[k]+array2[k]);
    array3.push(sum);    
}
console.log(array3);

Upvotes: 0

irishchesslegend
irishchesslegend

Reputation: 49

For all of the beginners coming across this question who may not be at the level to use map / reduce or ternary operators..

 let sum = 0;
 let nums = []

 for (let i = 0; i < array1.length; i++){
     sum = array1[i] + array2[i];
     nums.push(sum)
   }

 return nums

Upvotes: 4

FrontEnd Expert
FrontEnd Expert

Reputation: 5803

All the above mentioned answer is correct,

Using reduce. I just want to add my answer might be simple and useful.

var array1 = [1,2,3,4];
var array2 = [5,6,7,8];

const reducer = (accumulator, currentValue, index, array) => {
    let val = currentValue + array2[index];
    accumulator.push(val);
    return accumulator;
}


console.log(array1.reduce(reducer, []));

Thanks..

Upvotes: 1

Eric Chang
Eric Chang

Reputation: 2753

In ES6+, you can use arrow function to make the code clear:

var x = [1,2,3];
var y = [2,3,4];
var sum = x.map( (val, i) => val + y[i] );

console.log(sum); //Array [3, 5, 7]


var z = [3,4,5];
var add3 = x.map( (val, i) => val + y[i] + z[i] );

console.log(add3); //Array [6, 9, 12]

Upvotes: 1

edu4java
edu4java

Reputation: 1

Generic solution for N arrays of possibly different lengths using functional programming in one line ;)

const sumArrays = as => as.filter(a => a.length).length ? [as.filter(a => a.length).reduce((r, a) => r + a.shift(), 0), ...sumArrays(as)] : []

console.log(sumArrays([[1, 2, 3], [100], [11, 22, 33, 44], []]))

Upvotes: 0

Paulo Tijero
Paulo Tijero

Reputation: 59

Another way to do it could be like that

var array1 = [1,2,3,4];
var array2 = [5,6,7,8];

var sum = [...array1].map((e,i)=> e+array2[i]); //[6,8,10,12]

In this case [...array1] is the same to [1,2,3,4]

Upvotes: 4

jo_va
jo_va

Reputation: 13963

Here is a generic solution for N arrays of possibly different lengths.

It uses Array.prototype.reduce(), Array.prototype.map(), Math.max() and Array.from():

function sumArrays(...arrays) {
  const n = arrays.reduce((max, xs) => Math.max(max, xs.length), 0);
  const result = Array.from({ length: n });
  return result.map((_, i) => arrays.map(xs => xs[i] || 0).reduce((sum, x) => sum + x, 0));
}

console.log(...sumArrays([0, 1, 2], [1, 2, 3, 4], [1, 2])); // 2 5 5 4

Upvotes: 32

Roman Volyanskiy
Roman Volyanskiy

Reputation: 1

This example will work with different length variation:

let getSum = (arr1, arr2) =>  {
   let main = arr1.length >= arr2.length ? arr1 : arr2;
   let sec = arr1.length < arr2.length ? arr1 : arr2;
   return main.map((elem, i) => sec[i] ? elem + sec[i] : elem)
}

Upvotes: 0

Penny Liu
Penny Liu

Reputation: 17438

You can use the _.unzipWith method from the Lodash library.

var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8];
var array = [array1, array2];
console.log(_.unzipWith(array, _.add));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Upvotes: 3

rlib
rlib

Reputation: 7867

You can do it using some functional style:

const a = [1,2,3]
const b = [4,5,6]

const f= a.concat(b).map((v,i,arr)=>{
  if ( i<arr.length) return v+arr[i+arr.length/2]
}).filter(n=>!isNaN(n))

console.log(f)

Upvotes: 1

Venkat.R
Venkat.R

Reputation: 7746

Below example will work even with length variation and few more use cases. check out. you can do prototyping as well if you needed.

function sumArray(a, b) {
      var c = [];
      for (var i = 0; i < Math.max(a.length, b.length); i++) {
        c.push((a[i] || 0) + (b[i] || 0));
      }
      return c;
}

// First Use Case.
var a = [1, 2, 3, 4];
var b = [1, 2, 3, 4];
console.log( sumArray(a, b) );

// Second Use Case with different Length.
var a = [1, 2, 3, 4];
var b = [1, 2, 3, 4, 5];
console.log( sumArray(a, b) );

// Third Use Case with undefined values and invalid length.
var a = [1, 2, 3, 4];
var b = [];
b[1] = 2;
b[3] = 4;
b[9] = 9;
console.log( sumArray(a, b) );

Upvotes: 7

Dang Cong Duong
Dang Cong Duong

Reputation: 506

var arr = [1,2,3,4];
var arr2 = [1,1,1,2];

var squares = arr.map((a, i) => a + arr2[i]);

console.log(squares);

Upvotes: 26

Linmon
Linmon

Reputation: 41

Just merge Popovich and twalters's answer.

Array.prototype.SumArray = function (arr) {

        var sum = this.map(function (num, idx) {
          return num + arr[idx];
        });

        return sum;
    }
var array1 = [1,2,3,4];
var array2 = [5,6,7,8];
var sum = array1.SumArray(array2);
console.log(sum); // [6,8,10,12]

Upvotes: 4

twalters
twalters

Reputation: 1234

I know this is an old question but I was just discussing this with someone and we came up with another solution. You still need a loop but you can accomplish this with the Array.prototype.map().

var array1 = [1,2,3,4];
var array2 = [5,6,7,8];

var sum = array1.map(function (num, idx) {
  return num + array2[idx];
}); // [6,8,10,12]

Upvotes: 109

Amir Popovich
Amir Popovich

Reputation: 29836

You can't avoid the loop, but you can do this once and add a function to all Array objects using Array.prototype.

Here's and example:

// Add a SumArray method to all arrays by expanding the Array prototype(do this once in a general place)
Array.prototype.SumArray = function (arr) {
    var sum = [];
    if (arr != null && this.length == arr.length) {
        for (var i = 0; i < arr.length; i++) {
            sum.push(this[i] + arr[i]);
        }
    }

    return sum;
}

// here's your code
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8];
var sum = array1.SumArray(array2);
console.log(sum); // [6,8,10,12]

Here's your Fiddle.

Upvotes: 3

Related Questions