10

I have array like this

abcArr = [["A", 10], ["B", 20], ["A",30],["C",40]]

how can I group and sum values by A, B, C...

$.each(abcArr , function() {
    if (this[0] == this[0]) { 
      this[1] + this[1] 
    }; // I know this will simple double [1] values :(
});

desired result should be

[["A", 40], ["B", 20], ["C",30]]
1
  • Are you willing to use underscore.js? Commented Jan 20, 2013 at 18:24

3 Answers 3

19

Here's a plain javascript way to do it that collects the unique indexes in a map and totals them as it does, then regenerates the array with the totals:

abcArr = [["A", 10], ["B", 20], ["A",30],["C",40]];

var items = {}, base, key;
for (var i = 0; i < abcArr.length; i++) {
    base = abcArr[i];
    key = base[0];
    // if not already present in the map, add a zeroed item in the map
    if (!items[key]) {
        items[key] = 0;
    }
    // add new item to the map entry
    items[key] += base[1];
}

// Now, generate new array
var outputArr = [], temp;
for (key in items) {
    // create array entry for the map value
    temp = [key, items[key]]
    // put array entry into the output array
    outputArr.push(temp);
}

// outputArr contains the result

Working demo: http://jsfiddle.net/jfriend00/vPMwu/


Here's a way using jQuery's .each:

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]);
});

// outputArr contains the result
document.body.innerHTML = JSON.stringify(outputArr);

Working demo: http://jsfiddle.net/jfriend00/Q8LLT/

Sign up to request clarification or add additional context in comments.

8 Comments

You beat me in speed, and I can't see how to beat you in quality with just pure javascript. +1
it's works... thank you very much, I will take a time to try to understand function... thank you
@InTry are you still interested in an underscore.js two-liner?
If you have a time, why not... I have looked on underscore page, its "groupBy" function? I did not give a try
@InTry groupBy, then do some mapping. I'm giving it a try right now.
|
6

Underscore.js has groupBy, and the rest can be done by mapping over reduce (that is, reducing each group to one element

abcArr = [["A", 10], ["B", 20], ["A",30],["C",40]]

var grouped = _.groupBy(abcArr, function(x){return x[0]})
var result  = _.map(grouped, function(x){
    return _.reduce(x, function(x,y){
        return [y[0], x[1]+y[1]];
    }, [,0])
})

http://jsfiddle.net/srvKQ/

Or (minified)

abcArr = [["A", 10], ["B", 20], ["A",30],["C",40]]

var result = _.map(
    _.groupBy(abcArr, function(x){return x[0]}),
    function(x){return _.reduce(
        x, function(x,y){return [y[0], x[1]+y[1]]}, [,0]
)});

http://jsfiddle.net/srvKQ/1/

Comments

0

You can use Array.reduce() and Map().

var abcArr= [["A", 10], ["B", 20], ["A",30],["C",40]]

var groupValues = abcArr.reduce(function (obj, item) {
    obj[item[0]] = obj[item[0]] || [];
    obj[item[0]] = +obj[item[0]] + +item[1]; // add (+) before variable so it's cast to numeric 
    return obj;
}, {});

var groupData = Object.keys(groupValues).map(function (key) {
    return [key, groupValues[key]];
});

console.log(groupData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.