1

Here is my JavaScript object. I want to have a method to dynamically generate an object grouped by one or more attributes. The parameter attrs is an array, which contains some attributes for grouping.

var input= [
    {fistname:'Joe', age:'10', sex:'boy', class:'3'},
    {fistname:'Tom', age:'11', sex:'boy', class:'3'},
    {fistname:'Amily', age:'10', sex:'girl', class:'3'},
    {fistname:'Bob', age:'11', sex:'boy',class:'4'},
    {fistname:'Susan', age:'12', sex:'girl', class:'4'}
]

var attrs = ['age', 'class'];

function json2group(input, attrs){...}

Result:

[
    {
        label:'10',
        groups:[
            {
                label:'3',
                groups:[
                    {fistname:'Joe', age:'10', sex:'boy', class:'3'},
                    {fistname:'Amily', age:'10', sex:'girl', class:'3'}
                ]
            }
        ]
    },
    {
        label:'11',
        groups:[
            {
                label:'3',
                groups:[
                    {fistname:'Tom', age:'11', sex:'boy', class:'3'}
                ]
            },
            {
                label:'4',
                groups:[
                    {fistname:'Bob', age:'11', sex:'boy',class:'4'}
                ]
            }
        ]
    },
    {
        label:'12',
        groups:[
            {
                label:'4',
                groups:[
                    {fistname:'Susan', age:'12', sex:'girl', class:'4'}
                ]
            }
        ]
    }
]

Please help me.

1
  • 1
    The lodash groupBy function should help: lodash.com/docs#groupBy Commented Oct 16, 2014 at 16:05

3 Answers 3

1

You can use pure JS.

var input = [
    {fistname:'Joe', age:'10', sex:'boy', class:'3'},
    {fistname:'Tom', age:'11', sex:'boy', class:'3'},
    {fistname:'Amily', age:'10', sex:'girl', class:'3'},
    {fistname:'Bob', age:'11', sex:'boy',class:'4'},
    {fistname:'Susan', age:'12', sex:'girl', class:'4'}
];

var attrs = ['age', 'class'];

function GroupByArbitraryNumOfGroup(array, attrs) {
    var output = [];
    for (var i = 0; i < array.length; ++i) {
        var ele = array[i];
        var groups = output;
        for (var j = 0; j < attrs.length; ++j) {
            var attr = attrs[j];
            var value = ele[attr];
            var gs = groups.filter(function(g) {
                return g.hasOwnProperty('label') && g['label'] == value;
            });
            if (gs.length == 0) {
                var g = {};
                g['label'] = value;
                g['groups'] = [];
                groups.push(g);
                groups = g['groups'];
            } else {
                groups = gs[0]['groups'];
            }
        }
        groups.push(ele);
    }
    return output;
}

var o = GroupByArbitraryNumOfGroup(input, attrs);

And you will get o as

[{
    'label': '10',
    'groups': [{
        'label': '3',
        'groups': [{
            'fistname': 'Joe',
            'age': '10',
            'sex': 'boy',
            'class': '3'
        }, {
            'fistname': 'Amily',
            'age': '10',
            'sex': 'girl',
            'class': '3'
        }]
    }]
}, {
    'label': '11',
    'groups': [{
        'label': '3',
        'groups': [{
            'fistname': 'Tom',
            'age': '11',
            'sex': 'boy',
            'class': '3'
        }]
    }, {
        'label': '4',
        'groups': [{
            'fistname': 'Bob',
            'age': '11',
            'sex': 'boy',
            'class': '4'
        }]
    }]
}, {
    'label': '12',
    'groups': [{
        'label': '4',
        'groups': [{
            'fistname': 'Susan',
            'age': '12',
            'sex': 'girl',
            'class': '4'
        }]
    }]
}]
Sign up to request clarification or add additional context in comments.

Comments

0

I have found this Underscore.js groupBy multiple values

It's almost the same what I want. Using 'lodash.groupBy' should be all right, too.

Comments

0

You can try Alasql library to prepare your complex structure.

Here I prepared an example with two attributes:

var input= [ {fistname:'Joe', age:'10', sex:'boy', class:'3'},
             {fistname:'Tom', age:'11', sex:'boy', class:'3'} ];

function json2group(input, attr){
    var res1 = alasql('SELECT '+attr[0]+' AS label0,'+attr[1]+' AS label1, \
         ARRAY({label:'+attr[0]+',groups:_}) AS groups1 FROM ? GROUP BY label0,label1',[input]);
    return alasql('SELECT label0 AS label, ARRAY({label:label1,groups:groups1}) \
         AS groups FROM ? GROUP BY label', [res1]);
};

var res = json2group(input, ["age","class"]);

You can try it in jsFiddle, it produces exactly your result.

1 Comment

Your result data structure is not trivial, so you could write me, and I can help you.

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.