user1720275
user1720275

Reputation: 57

Using JQuery/JavaScript how would I group values in an array of objects and create a new array of objects from the groups

I have an Array of JSON objects like so

var dataSet1 = [{
"id": "1",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "5",
    "grade": "X"
}, {
"id": "2",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "5",
    "grade": "A"
}, {
"id": "3",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "4",
    "grade": "X"
},
{
"id": "4",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "5",
    "grade": "A"
}];

I would like to loop through this data set and create a new array of objects that merge the objects with similar "grade" properties and preserves a list of their associated "id" and "version" values like so

OLD Objects with "grade" property equal to 'X'

{
"id": "1",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "5",
    "grade": "X"
} 
{
"id": "3",
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "version": "4",
    "grade": "X"
}

NEW Object with "grade" property equal to 'X'

{
"ids":{"id":"1","id":"3"}
    "engine": "Trident",
    "browser": "Internet Explorer 4.0",
    "platform": "Win 95+",
    "versions":{ "version":"4", "version":"5"}
    "grade": "X"
}

Im pretty sure I have to use the $.each and $.grep function like so

    $.each(dataSet1, function (index, value) {


tsaGrade = dataSet1[index].grade;

result = $.grep(dataSet1, function (e) {
    return e.grade == tsaGrade;
})

and placing the ids and versions in new arrays, but I get lost on how to prevent the each loop from excluding the values that is already grouped the next time it loops through the data set.

Upvotes: 4

Views: 2757

Answers (1)

Elise
Elise

Reputation: 5124

If you're willing to use Underscore.js, this becomes pretty trivial.

Assuming data is your original list of json objects, this will achieve what you're after:

var groups = [];
var by_grade = _.groupBy(data, function(obj) { return obj['grade'] });
_.each(by_grade, function(objs, grade) {
    var group = {};
    group['grade'] = grade;
    group['ids'] = _.pluck(objs, 'id');
    group['versions'] = _.pluck(objs, 'version');
    // Use the following if the value is known to be 
    // the same for all grouped objects
    group['platform'] = objs[0]['platform'];
    // And the rest...
    groups.push(group);
});

_.groupBy() will group your objects by grade, resulting in two objects with the keys X and A, whose values are lists of objects with the corresponding grades. You can then loop over each of the two lists of objects, plucking the required values so that they will be added as lists to your new object. Difficult to describe fully, but see the log messages on this Fiddle :)

Edit

Instead of objs['platform'] should be using objs[0]['platform'] for all attributes that you know are the same for items with the same grade.

Edit 2

Building from this, a better approach instead of _.each would probably be _.map:

groups = _.map(by_grade, function(objs, grade) {
    return {
        grade: grade, 
        browsers: _.pluck(objs, 'browser'),
        ids: _.pluck(objs, 'id'),
        versions: _.pluck(objs, 'id'),
        engines: _.pluck(objs, 'engine')
        // etc
    }
});

Fiddle

Upvotes: 2

Related Questions