y2knoproblem
y2knoproblem

Reputation: 570

Add values in a two-dimensional array with JavaScript

I want to merge and add the following 2D array:

var arr = [
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["DIME", 0.1],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01]
    ];

Resulting in a 2D array that looks like this:

 arr = [
     ["TWENTY", 80],
     ["TEN", 10],
     ["FIVE", 5],
     ["QUARTER", 0.50],
     ["DIME", 0.20],
     ["PENNY", 0.04]
     ];

Basically I'm adding up the number values and condensing the string values. I tried map, reduce, and for loops but this one has me stumped.

Upvotes: 3

Views: 360

Answers (2)

Michael Laszlo
Michael Laszlo

Reputation: 12239

You have an array with key, value tuples. You can iterate over these tuples, store each new key in an object, and increment the value as you come upon subsequent tuples the same key. If you keep an array of keys in the order in which you encountered them, you can map the array of keys to a result array.

But it would be foolish to go to all this trouble when you could use the purely functional approach shown in Nit's answer.

Below is the ugly approach. Don't do this. Do what Nit says.

function addArray(tuples) {
  var hash = {},
      keys = [];
  tuples.forEach(function (tuple) { // Iterate over [key, value] tuples.
    var key = tuple[0],
        value = tuple[1];
    if (hash[key] === undefined) {  // Is it a new key?
      keys.push(key);               // Then add it to keys.
      hash[key] = value;            // And set the initial value.
    } else {
      hash[key] += value;           // Otherwise, increment the value.
    }
  });
  return keys.map(function (key) {  // Map the keys to tuples.
    return([key, hash[key]]);
  });
};

var arr = [
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["DIME", 0.1],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01]
];

var added = addArray(arr);

added.forEach(function (tuple) {
  document.write(JSON.stringify(tuple) + '<br />');
});

Upvotes: 2

Etheryte
Etheryte

Reputation: 25321

All you really need is a reduce and a map, which could probably add up to a good MapReduce joke.

var arr = [
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TWENTY", 20],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["DIME", 0.1],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01],
    ["PENNY", 0.01]
];
var obj = arr.reduce(function (out, el) {
    out[el[0]] = (out[el[0]] || 0) + el[1];
    return out;
}, {});
var out = Object.keys(obj).map(function (key) {
    return [key, obj[key]]
}); //[["TWENTY",80],["TEN",10],["FIVE",5],["ONE",1],["QUARTER",0.5],["DIME",0.2],["PENNY",0.04]]

Upvotes: 2

Related Questions