1

I want to iterate through an array loop and do stuff according to the property name and value of the objects within the array.

The array is retrieved from a very "flat" JSON file, that is a collection of git commit logs from several git repositories (parsed to JSON from bash through this project).

Some of the things I would like to do would be:

  • sort the commits by their timestamp.
  • filter them by repository, and then do things with the data.
  • filter them by author_email, and then do things with the data.
  • calculate impact on each repository recursively.

But what I'm mostly interested in is how can I select/group/filter all commits that share a certain property value (like repository or author_email or date_day_week) without specifying any explicit value?

I have done it manually (see 7th line from bottom to top in the block of code below):

// == request and parse JSON data == //
// define data source
var data_source = "src/json/data.json";
// request the data
var xhr = new XMLHttpRequest();
xhr.open("GET", data_source);
xhr.onreadystatechange = function () {
    if (this.readyState !== 4) { return; }
    if ((this.status >= 200 && this.status < 300) || this.status === 0) {
        // get raw data
        data_JSON = this.responseText;
        // parse JSON data to JavaScript format
        data_parsed = JSON.parse(data_JSON);
        // manipulate data 'outside' the xhr request to keep things tidy
        manipulateData(data_parsed);
    } else {
        console.log('There was an error completing the XMLHttpRequest...');
    }
};
xhr.send();

// create a callback function to do stuff 'outside' xhr
function manipulateData(object){
    // define root object
    var commit = object.commits;
    // loop through every item so that we can iterate with them
    for (var i = 0; i < commit.length; i++){
        // define 'commit[i]' as 'item' so that code is more legible
        var item = commit[i];
        // list property names and their values on console
        for (var key in item) {
            if (item.hasOwnProperty(key)) {
                // list only items under 'lemon' repository <-- this is where I need it to be generic so I can group/filter all items under a common repository and do things with it
                if (item.repository == 'lemon') {
                    console.log(key + " -> " + item[key]);
                }
            }
        }
    }
}

But what I would like to do is to group/filter all commits that share a given property value (i.e. repository lemon, apple, orange, etc) together dynamically. Once I know how to do that, I'll hopefully be able to do the same with other property names that may share property values, like author_email, date_day_week, date_month_name, insertions, etc.

Below is the original data.json file, declared as a variable at var data_source = "src/json/data.json";:

{
    "commits":[
        {
            "repository":"lemon",
            "commit_nr":"1",
            "commit_hash":"146b76e91a269a9c06dcc4eb6854f76a7900a08e",
            "commit_hash_abbreviated":"146b76e",
            "tree_hash":"4090f728f1759a16df7dde49bf86f7536354ae02",
            "tree_hash_abbreviated":"4090f72",
            "parent_hashes":"",
            "parent_hashes_abbreviated":"",
            "author_email":"[email protected]",
            "date_day_week":"Fri",
            "date_month_name":"Feb",
            "date_month_day":"25",
            "date_hour":"09:59:17",
            "date_year":"2011",
            "date_hour_gmt":"-0800",
            "author_date_unix_timestamp":"1298656757",
            "date_iso_8601":"2011-02-25",
            "committer_email":"[email protected]",
            "files_changed":"46",
            "insertions":"3162",
            "deletions":"",
            "impact":"3162"
        },
        {
            "repository":"lemon",
            "commit_nr":"2",
            "commit_hash":"d6c8de134e0ee33b3837795250c9fffa02e57738",
            "commit_hash_abbreviated":"d6c8de1",
            "tree_hash":"f4ec855ed6c4402304500a68a74ff38943a47d3d",
            "tree_hash_abbreviated":"f4ec855",
            "parent_hashes":"146b76e91a269a9c06dcc4eb6854f76a7900a08e",
            "parent_hashes_abbreviated":"146b76e",
            "author_email":"[email protected]",
            "date_day_week":"Fri",
            "date_month_name":"Feb",
            "date_month_day":"25",
            "date_hour":"11:27:24",
            "date_year":"2011",
            "date_hour_gmt":"-0800",
            "author_date_unix_timestamp":"1298662044",
            "date_iso_8601":"2011-02-25",
            "committer_email":"[email protected]",
            "files_changed":"5",
            "insertions":"46",
            "deletions":"40",
            "impact":"6"
        },
        {
            "repository":"lemon",
            "commit_nr":"3",
            "commit_hash":"9a27e12968397923df17a424672447eee06ea248",
            "commit_hash_abbreviated":"9a27e12",
            "tree_hash":"5ceb1539ee9879f7d9043123ee36c4c44c93e64c",
            "tree_hash_abbreviated":"5ceb153",
            "parent_hashes":"d6c8de134e0ee33b3837795250c9fffa02e57738",
            "parent_hashes_abbreviated":"d6c8de1",
            "author_email":"[email protected]",
            "date_day_week":"Fri",
            "date_month_name":"Feb",
            "date_month_day":"25",
            "date_hour":"11:52:09",
            "date_year":"2011",
            "date_hour_gmt":"-0800",
            "author_date_unix_timestamp":"1298663529",
            "date_iso_8601":"2011-02-25",
            "committer_email":"[email protected]",
            "files_changed":"6",
            "insertions":"151",
            "deletions":"81",
            "impact":"70"
        },
        {
            "repository":"apple",
            "commit_nr":"1",
            "commit_hash":"61180570cb0cbc2233f841436d924ab43eeb7c7e",
            "commit_hash_abbreviated":"6118057",
            "tree_hash":"f652101ca189f92fc70767203879af9aeb9cec1e",
            "tree_hash_abbreviated":"f652101",
            "parent_hashes":"",
            "parent_hashes_abbreviated":"",
            "author_email":"[email protected]",
            "date_day_week":"Fri",
            "date_month_name":"Oct",
            "date_month_day":"1",
            "date_hour":"17:01:48",
            "date_year":"2010",
            "date_hour_gmt":"+0700",
            "author_date_unix_timestamp":"1285927308",
            "date_iso_8601":"2010-10-01",
            "committer_email":"[email protected]",
            "files_changed":"0",
            "insertions":"",
            "deletions":"",
            "impact":"0"
        },
        {
            "repository":"apple",
            "commit_nr":"2",
            "commit_hash":"3d3d52f0197aa501c9c4d6e4c245604e696097e1",
            "commit_hash_abbreviated":"3d3d52f",
            "tree_hash":"a1e190dfc9e63c7895884fbc9c1cbfa1473a27c2",
            "tree_hash_abbreviated":"a1e190d",
            "parent_hashes":"61180570cb0cbc2233f841436d924ab43eeb7c7e",
            "parent_hashes_abbreviated":"6118057",
            "author_email":"[email protected]",
            "date_day_week":"Mon",
            "date_month_name":"Oct",
            "date_month_day":"11",
            "date_hour":"11:30:08",
            "date_year":"2010",
            "date_hour_gmt":"+0700",
            "author_date_unix_timestamp":"1286771408",
            "date_iso_8601":"2010-10-11",
            "committer_email":"[email protected]",
            "files_changed":"24",
            "insertions":"452",
            "deletions":"",
            "impact":"452"
        },
        {
            "repository":"apple",
            "commit_nr":"3",
            "commit_hash":"1b5b80db7dd8a252d40b6331ba7ba85dd4af90c6",
            "commit_hash_abbreviated":"1b5b80d",
            "tree_hash":"89d70a6ac4b071aea13055f91a9907c6480e99d3",
            "tree_hash_abbreviated":"89d70a6",
            "parent_hashes":"3d3d52f0197aa501c9c4d6e4c245604e696097e1",
            "parent_hashes_abbreviated":"3d3d52f",
            "author_email":"[email protected]",
            "date_day_week":"Mon",
            "date_month_name":"Oct",
            "date_month_day":"11",
            "date_hour":"14:17:47",
            "date_year":"2010",
            "date_hour_gmt":"+0700",
            "author_date_unix_timestamp":"1286781467",
            "date_iso_8601":"2010-10-11",
            "committer_email":"[email protected]",
            "files_changed":"1",
            "insertions":"15",
            "deletions":"",
            "impact":"15"
        },
        {
            "repository":"orange",
            "commit_nr":"1",
            "commit_hash":"dac34582a10de94cd305afc47cd888ee59c30e35",
            "commit_hash_abbreviated":"dac3458",
            "tree_hash":"9114b1b23157894f3fac49ecd7686aadc2cc7678",
            "tree_hash_abbreviated":"9114b1b",
            "parent_hashes":"",
            "parent_hashes_abbreviated":"",
            "author_email":"[email protected]",
            "date_day_week":"Tue",
            "date_month_name":"Feb",
            "date_month_day":"4",
            "date_hour":"01:24:51",
            "date_year":"2014",
            "date_hour_gmt":"-0800",
            "author_date_unix_timestamp":"1391505891",
            "date_iso_8601":"2014-02-04",
            "committer_email":"[email protected]",
            "files_changed":"1",
            "insertions":"4",
            "deletions":"",
            "impact":"4"
        },
        {
            "repository":"orange",
            "commit_nr":"2",
            "commit_hash":"077fa1e30bfb1b02241d8fd603941a250ded983d",
            "commit_hash_abbreviated":"077fa1e",
            "tree_hash":"d8eb6b28fd3798b0490fd7376c29781cdaffd42d",
            "tree_hash_abbreviated":"d8eb6b2",
            "parent_hashes":"dac34582a10de94cd305afc47cd888ee59c30e35",
            "parent_hashes_abbreviated":"dac3458",
            "author_email":"[email protected]",
            "date_day_week":"Wed",
            "date_month_name":"Feb",
            "date_month_day":"5",
            "date_hour":"20:24:48",
            "date_year":"2014",
            "date_hour_gmt":"+0700",
            "author_date_unix_timestamp":"1391606688",
            "date_iso_8601":"2014-02-05",
            "committer_email":"[email protected]",
            "files_changed":"9",
            "insertions":"374",
            "deletions":"",
            "impact":"374"
        },
        {
            "repository":"orange",
            "commit_nr":"3",
            "commit_hash":"e217e8d4b4e366331d5e2a196215867c60215bfc",
            "commit_hash_abbreviated":"e217e8d",
            "tree_hash":"95d4002df3db4d0f3912b0609a3680dd3d751a92",
            "tree_hash_abbreviated":"95d4002",
            "parent_hashes":"077fa1e30bfb1b02241d8fd603941a250ded983d",
            "parent_hashes_abbreviated":"077fa1e",
            "author_email":"[email protected]",
            "date_day_week":"Thu",
            "date_month_name":"Feb",
            "date_month_day":"6",
            "date_hour":"14:44:00",
            "date_year":"2014",
            "date_hour_gmt":"+0700",
            "author_date_unix_timestamp":"1391672640",
            "date_iso_8601":"2014-02-06",
            "committer_email":"[email protected]",
            "files_changed":"1",
            "insertions":"1",
            "deletions":"3",
            "impact":"-2"
        }
    ]
}

Any help is appreciated!

3
  • Can you give an example of what you are going to do inside that if statement? I'm trying to understand what you're trying to achieve. Commented Apr 26, 2014 at 22:19
  • If you just want to group what you received you could create an new array and have the first dimension be the repository. i.e. yourarray[repository].push(item) Commented Apr 26, 2014 at 22:32
  • @Dan once I have filtered/grouped a set of object name & value, I'll be able to iterate through the items and do things like render graphs as these. ;) Commented Apr 27, 2014 at 7:31

1 Answer 1

6

Try this:

function groupBy(data,key, val){
    var arr=[];
    for(var i in data){
        if(data[i][key]==val) arr.push(data[i])
    }
    return arr;
}

console.log(groupBy(object.commits,"repository","lemon"))

And for grouping without specifying val:

function groupByAuto(data, key){
    var groups={};
    for(var i in data){
        if(!groups.hasOwnProperty(data[i][key])) groups[data[i][key]]=[];
        groups[data[i][key]].push(data[i]);
    }
    return groups;
}
console.log(groupByAuto(data.commits, "repository"))
Sign up to request clarification or add additional context in comments.

5 Comments

I must say this was pretty smartly done! It worked with other sets of key x val as well (like author_email)! But would there be any way to create separate arrays for each grouped val automatically, by running a modified function like: groupByAuto(object.commits, "repository"). The nature of this data is such that I don't know which values will be listed (though key won't change) - so it would really save me a lot of time not to have to specify val, in this case.
Something like "loop through the specified data.key (like object.commits.repository) and create a new array when it finds a val. if (previous val === current val) add it to array, otherwise keep creating new arrays - as long as there is a new val"... To be honest I don't know how I would do this, nor if it is the best approach. Hence the question. :P
You would only have to alter the if statement for this. if(data[i][key] in arr) { //add to existing array } else { // create new array }
@WallaceSidhrée added groupByAuto function to answer
@juvian this is absolutely gorgeous code! I've made a simplified jsfiddle applying both your answers, so that others might see how useful this is. This is greatly appreciated, now I can move on to the next step! Cheers!!

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.