1

Only just introduced to _Underscore so this may be totally nonsense but I'm wondering if the library can indeed do what I want.

I have an object containing 5 items:

Name, v2007,v2008,v2009,v2010

I simply want to go through the entire object and get the SUM of each distinct value in Name (much similar to SQL's GroupBy and SUM).

I have the following:

var distincts = [];
$.each(tmp, function (key, value) {
    $.each(value, function (fieldName, fieldValue) {
        if (fieldName == 'Name') {
            if ($.inArray(fieldValue, distincts) == -1) {
                distincts.push(fieldValue);
            }
        }
    });
});

$.each(distincts, function (a, b) {
    var t = _.where(tmp, {Name: b});
    var sum = _.reduce(t.v2007, function (memo, num) {
        return memo + num;
    }, 0)
    console.log(sum);
});

Which is returning 0 all the time, in fact I'm not sure how to retrieve a SUM of fields v2011, v2013 other than hard-coding them in which is simply not practical!

Can someone help me a little here, is there a simple way of getting the _Underscore library to SUM all fields (that, say, start with 'v') based on a Group of the Name?

1
  • Could you show us an example tmp object (in JSON format)? Btw, you shouldn't mix Underscore's and jQuery's each functions Commented Oct 26, 2012 at 13:12

2 Answers 2

3

I think this does what you want:

var groups = _.groupBy(function(name) { return name.charAt(0) });
var sums = _.map(groups, function(group) {
    return _.reduce(group, function (a, b) { return a+b; }, 0);
});
Sign up to request clarification or add additional context in comments.

2 Comments

No offense, but shouldn't there be a simpler way to do this with underscore?
@Jess: I don't think so, Underscore is not a query language but a toolset of some functional helpers. I you find a simpler way, please provide another answer :-)
1

Here is a way I came up with that will take an array of objects and return a single object where the "keys" of the object are the grouped value and the "values" of the object are the aggregated value:

function groupBy(input, xCol, yCol) {

    var output = {};

    // This function can be easily changed to do max, min, avg, sum.
    var sum = function(row, idx) {
        if (!(row[xCol] in output)) {
            output[row[xCol]] = row[yCol];
        }
        else {
            output[row[xCol]] += row[yCol];         
        }
    };
    _.each(input, sum);

    return output;
}

And a test:

var input = [ {
    pn : "M1",
    date : "2014-01-01T00:00:00Z",
    qty : 1
}, {
    pn : "M1",
    date : "2014-01-01T00:00:00Z",
    qty : .5
}, {
    pn : "M2",
    date : "2014-01-04T00:00:00Z",
    qty : 2
} ];

it('should group by abc value, showing max.', function() {
    expect(groupBy(input, "pn", "qty")).toEqual({
        "M1" : 1.5,
        "M2" : 2
    });
});

This answer only nominally uses underscore for the foreach loop.

1 Comment

What do you think @Bergi?

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.