GoodCat
GoodCat

Reputation: 117

Grouping Data in Javascript

I have a CSV I am loading into memory via csv to array, this returns an array of objects with key value pairs for each row of data with the key being the column and the value being the data associated with that column. As such:

[{col1: 'id1', col2: '123', col3: '12/01/12'},
{col1: 'id1', col2: '100', col3: '12/01/12'},
{col1: 'id2', col2: '-100', col3: '12/01/12'},
{col1: 'id2', col2: '123', col3: '13/01/12'}]

What I want to be able to do is group data based on a specific column so for example for id1 on the data 12/01/12 what was the sum total of column col2. Or for id2 what was the difference between the value in col2 between 12/01/12 and 13/01/12.

Fairly new (1 week in) to JS so any advice on this would be much appreciated.

Upvotes: 2

Views: 9292

Answers (2)

cjg
cjg

Reputation: 2684

For grouping, I'd use the Array filter method. It takes a function that should return true if you wish to include an array element in the filtered array. So to get the rows for which col1 is 'id1' and col3 is '12/01/12', you would do:

var data = [{col1: 'id1', col2: '123', col3: '12/01/12'},
            {col1: 'id1', col2: '100', col3: '12/01/12'},
            {col1: 'id2', col2: '-100', col3: '12/01/12'},
            {col1: 'id2', col2: '123', col3: '13/01/12'}];

var grouped = data.filter(  function(row) {
                               return row.col3 == '12/01/12' && row.col1 == 'id1';
                            });

For summing a column within a group, you can use the Array reduce method. It takes as its first argument a "reducing" function that reduces the elements of an array to a single value. It takes as its optional second argument a starting value. The reducing function must take two arguments. On the first iteration, the first argument is the specified starting value, and on subsequent iterations, it's the return value of the function on the previous iteration. The second argument to the reducing function is an element of your array. So to sum the second column of your grouped data, you'd do:

var sumOfGrouped = grouped.reduce(function(sumSoFar, row) { return sumSoFar + parseInt(row.col2) }, 0);

Look at the other Array methods, and you will find others that could be useful for you depending on what you want to do.

Upvotes: 2

Toby Mellor
Toby Mellor

Reputation: 8215

I've created a function who's parameter is a String, representing the column name. In the example, I'm passing in "col1" -- the ID column.

The function creates an empty object. It loops through the data array and checks whether an object with the same ID has already been stored. If not, I'm creating a new property, which has the same name as the ID, and assigning an empty array to it.

This empty array will contain the objects who have the same ID.

Example

var data = [
    {col1: 'id1', col2: '123', col3: '12/01/12'},
    {col1: 'id1', col2: '100', col3: '12/01/12'},
    {col1: 'id2', col2: '-100', col3: '12/01/12'},
    {col1: 'id2', col2: '123', col3: '13/01/12'}
];

function sortData(columnName) {
    var sortedData = {};

    for (var i = 0; i < data.length; i++) {
        var object = data[i];

        if (Object.keys(sortedData).indexOf(object[columnName]) === -1) {
            sortedData[object[columnName]] = [];
        }

        sortedData[object[columnName]].push(object);
    }
    
    return sortedData;
}

console.log(sortData("col1"));

Upvotes: 2

Related Questions