NewBee
NewBee

Reputation: 63

Jquery array group by multiple elements and find total

I have an array like this:

abcArr = [["A", "dog", 10], ["B", "cat", 20], ["A", "dog", 30],["C", "pig", 40]] ["A", "cat", 30],  ["B", "cat", 20], ["A", "horse", 10];

I was looking at this post (jquery array group by) and I need something similar for my issue but I need to group my array based on 2 elements.

So my answer should look like this:

[["A", "dog", 40], ["B", "cat", 40], ["C", "pig", 40]] ["A", "cat", 30], ["A", "horse", 10];

I tried @jfriend00 's .each() approach to group just one field and it works, but I don't know how to adapt it to use two fields to group the data above.

abcArr = [["A", 10],["B", 20],["A", 30],["C", 40]];
var items = {},
  base, key;
$.each(abcArr, function(index, val) {
  key = val[0];
  if (!items[key]) {
    items[key] = 0;
  }
  items[key] += val[1];
});
var outputArr = [];
$.each(items, function(key, val) {
  outputArr.push([key, val]);
});

console.log(outputArr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Thanks.

Upvotes: 2

Views: 2379

Answers (1)

mhodges
mhodges

Reputation: 11116

What you can do is, instead of one field being used as the key for your items object, you can combine multiple keys, like so:

Note - jQuery is not necessary to solve this issue because JavaScript has the handy .reduce() and .map() functions built right in.

var abcArr = [["A", "dog", 10], ["B", "cat", 20], ["A", "dog", 30],["C", "pig", 40], ["A", "cat", 30],  ["B", "cat", 20], ["A", "horse", 10]];

// group the items by letter-animal and sum the results
var items = abcArr.reduce(function (results, current) {
  var letter = current[0];
  var animal = current[1];
  var value = current[2];
  
  // combine the two fields as the key to match on.. this is where the magic happens
  var key = letter + "-" + animal;
  if (!results[key]) {
    results[key] = 0;
  }
  results[key] += value;
  return results;
}, {});

// break the keys out from the hyphenated form back into individual array elements w/ value
var outputArr = Object.keys(items).map(function (key) {
  var splitKey = key.split("-");
  var letter = splitKey[0];
  var animal = splitKey[1];
  var itemValue = items[key];
  
  return [letter, animal, itemValue];
});

console.log(outputArr);

Alternatively with ES6 Syntax:

var abcArr = [["A", "dog", 10], ["B", "cat", 20], ["A", "dog", 30],["C", "pig", 40], ["A", "cat", 30],  ["B", "cat", 20], ["A", "horse", 10]];

var items = abcArr.reduce((results, [letter, animal, value]) => {
  var key = letter + "-" + animal;
  if (!results[key]) {
    results[key] = 0;
  }
  results[key] += value;
  return results;
}, {});

var outputArr = Object.keys(items).map(key => [...key.split("-"), items[key]]);

console.log(outputArr);

Upvotes: 1

Related Questions