2
\$\begingroup\$

I wrote a JavaScript source which regrouping by new key i.e. following JSON to the other:

{
    "items" : [
        {
            "company" : "A"
            , "name" : "Prod_A01" 
        }
        , {
            "company" : "A"
            , "name" : "Prod_A02"
        }
        , {
            "company" : "B"
            , "name" : "Prod_B01"
        }
    ]
}

to:

{
    "A" : [
        {
            "company" : "A"
            , "name" : "Prod_A01" 
        }
        , {
            "company" : "A"
            , "name" : "Prod_A02"
        }
    ]

    , "B" : [
        {
            "company" : "B"
            , "name" : "Prod_B01"
        }
    ]
}

And here is logic:

function regroup(collection, key){
    var novo_obj = {};
    var type = typeof collection;
    var keyGroup = [];

    getKeyGroup(collection, key, keyGroup);

    for(var i = 0; i < keyGroup.length; i++) {
        novo_obj[keyGroup[i]] = [];
        gatherElements(collection, key, keyGroup[i], novo_obj[keyGroup[i]]);
        //console.log(novo_obj);
    }
    console.log(JSON.stringify(novo_obj));
    return novo_obj;
}

function gatherElements(collection, key, value, arr){
    //console.log(collection);
    if(typeof collection == 'object'){
        var targetValue = collection[key];
        if(typeof targetValue != 'undefined' && targetValue == value){
            arr.push(collection);
        }else{
            for(var elem in collection){
                gatherElements(collection[elem], key, value, arr);
            }
        }
    }else if(typeof collection == 'array'){
        for(var i = 0; i < collection.length; i++) {
            getKeyGroup(collection[i], key, value, arr);
        }
    }
}

function getKeyGroup(collection, key, keygroup){
    var targetValue = '';
    if(typeof collection == 'object'){
        targetValue = collection[key];
        if(typeof targetValue != 'undefined'){
            keygroup.push(targetValue);
        }else{
            for(var elem in collection){
                getKeyGroup(collection[elem], key, keygroup);
            }
        }
    }else if(typeof collection == 'array'){
        console.log('isArr');
        for(var i = 0; i < collection.length; i++) {
            getKeyGroup(collection[i], key, keygroup);
        }
    }
    return keygroup;
}

function main(){
    var test = {
        items : [
            {
                company : "A"
                , name : "Prod_A01"
            }
            , {
                company : "A"
                , name : "Prod_A02"
            }
            , {
                company : "B"
                , name : "Prod_B01"
            }
        ]
    }
    regroup(test, "company");
}

However, I think looping every time does not look so good. I need to improve this source code.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I think you may be complicating things a lot. If I understand correctly you are basically after groupBy which you can find in lodash, or implement in a few lines of code:

function groupBy(coll, f) {
  return coll.reduce(function(acc, x) {
    var k = f(x);
    acc[k] = (acc[k] || []).concat(x);
    return acc;
  }, {});
}

var test = {
  items: [{
    company: "A", name: "Prod_A01"
  }, {
    company: "A", name: "Prod_A02"
  }, {
    company: "B", name: "Prod_B01"
  }]
};

var result = groupBy(test.items, function(x){return x.company});

JSON.stringify(result);
/*^
{
  "A": [
    {
      "company": "A",
      "name": "Prod_A01"
    },
    {
      "company": "A",
      "name": "Prod_A02"
    }
  ],
  "B": [
    {
      "company": "B",
      "name": "Prod_B01"
    }
  ]
}
*/

You can use this to group a collection (array of objects) by some property, test.items in this case. Also, I would leave the JSON part out of it, because it is irrelevant to the grouping algorithm.

\$\endgroup\$
3
  • \$\begingroup\$ wow. awesome! so simple!! \$\endgroup\$ Commented Apr 2, 2016 at 6:02
  • \$\begingroup\$ Got one more question. You mentioned about lodash. Why did you mentioned that? (Your code seems work nicely with native js) \$\endgroup\$ Commented Apr 2, 2016 at 6:05
  • \$\begingroup\$ Just because it is a popular library, you may use it and import only that function npmjs.com/package/lodash.groupby. Also in lodash it is a bit more flexible, you can do _.groupBy(test.items, 'company') \$\endgroup\$
    – elclanrs
    Commented Apr 2, 2016 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.