Zack T
Zack T

Reputation: 43

Combine unique items of an array of arrays while summing values - JS / lodash

I have an array that looks something like this:

currArray = 
 [ 
  ['a', 2],
  ['b', 3],
  ['c', 5],
  ['a', 2],
  ['b', 4],
  ['d', 6]
 ]

I am trying to combine the arrays that have the same value at [0], while adding the values at [1]. So the output would look like:

newArray = 
 [ 
  ['a', 4], 
  ['b', 7], 
  ['c', 5], 
  ['d', 6] 
 ]

Currently trying this via Vanilla JavaScript and lodash.

Any advice is much appreciated.

Upvotes: 2

Views: 124

Answers (4)

Lonnie Best
Lonnie Best

Reputation: 11364

You could use a Map to keep a running tally for each differing currArray[0]:

currArray = 
 [ 
  ['a', 2],
  ['b', 3],
  ['c', 5],
  ['a', 2],
  ['b', 4],
  ['d', 6]
 ];
 
 let map = new Map();
 currArray.forEach(function(subAry)
 {
  let runningTally = map.get(subAry[0]);
  if (runningTally)
  {
    map.set(subAry[0],runningTally + subAry[1]);
  }
  else
  {
    map.set(subAry[0],subAry[1]);
  }
 });
 let newArray = Array.from(map);
 console.log(newArray);

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 191976

You can use _.groupBy() with _.head() to group all entries with the same 1st item. Then map the groups, and sum (with _.sumBy() and _.last()) the 2nd elements of each group:

const currArray = [["a",2],["b",3],["c",5],["a",2],["b",4],["d",6]]

const result = _.map(
  _.groupBy(currArray, _.head), // group by the 1st item
  (group, key) => [key, _.sumBy(group, _.last)] // take the key from each group, and sum all the 2nd items of each group
)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

With lodash/fp you can create a function with _.flow() that groups the items by the 1st element, sum the 2nd elements of each group, and convert to entries:

const { flow, groupBy, head, mapValues, sumBy, last, toPairs } = _

const fn = flow(
  groupBy(head), // group by the 1st item
  mapValues(sumBy(last)), // take the key from each group, and sum all the 2nd items of each group
  toPairs // convert to entries
)

const currArray = [["a",2],["b",3],["c",5],["a",2],["b",4],["d",6]]

const result = fn(currArray)

console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

Upvotes: 2

ssbarbee
ssbarbee

Reputation: 1712

We can use hashmaps to store the sum, and then map the hashmap to array.

currArray = 
 [ 
  ['a', 2],
  ['b', 3],
  ['c', 5],
  ['a', 2],
  ['b', 4],
  ['d', 6]
 ]

// create a hash map
const currArrInfo = {};

// fill the hash map
currArray.forEach((miniArray) => {
    currArrInfo[miniArray[0]] = currArrInfo[miniArray[0]] || 0;
    currArrInfo[miniArray[0]]+=currArrInfo[miniArray[1]];
});

// map the hash map to array
currArray = Object.keys(currArrInfo).map((key) => [key, currArrInfo[key]]);

Upvotes: 2

blex
blex

Reputation: 25634

You can use Array.reduce():

const currArray = [
  ['a', 2],
  ['b', 3],
  ['c', 5],
  ['a', 2],
  ['b', 4],
  ['d', 6]
];

const result = currArray.reduce((res, [key, val]) => {
  const correspondingArr = res.find(arr => arr[0] === key);
  if (correspondingArr) {
    correspondingArr[1] += val;
  } else {
    res.push([key, val]);
  }
  return res;
}, []);

console.log(result);

Upvotes: 3

Related Questions