Search code examples
javascriptarraysdata-structuresgroupinglodash

lodash group array of nested objects by key


I have the following data:

  var data = {
  "features": [
    {
      "properties": {
        "route_id": 522,
        "name": "the Mekong",
        "tour_id": 538
      }
    },{
      "properties": {
        "route_id": 522,
        "name": "Cambodia & the Mekong",
        "tour_id": 545
      }
    },{
      "properties": {
        "route_id": 521,
        "name": "Cambodia",
        "tour_id": 537
      }
    }
  ]
}

Now, I want to group values that have similar "route_id" into a nested array of objects; ultimately using lodash; so that the expected result will be as following:

var result = {
  "features": [
    {
      "properties": [{
        "route_id": 522,
        "name": "the Mekong",
        "tour_id": 538
        },{
        "route_id": 522,
        "name": "Cambodia & the Mekong",
        "tour_id": 545
      }]
    },{
      "properties": {
        "route_id": 521,
        "name": "Cambodia",
        "tour_id": 537
      }
    }
  ]
}

I tried using _.group but I don't know how to get the nested array under one object. Also note that there will be other keys along with the "properties" key but they're not relevant to the structure.


Solution

  • If the objects in the features collection contains one key, properties, then I strongly advice to normalize the structure, removing the properties key. Nevertheless, here's an implementation that you might be looking for.

    var result = {
      features: _(data.features)
        // get all routes (get rid of properties key)
        .map('properties') 
        // group by route_id
        .groupBy('route_id') 
        // place properties key again
        .map(function(group) { return { properties: group };})
        // get grouped features
        .value()
    };
    

    Function references: lodash#map, lodash#groupBy

    var data = {
      "features": [{
        "properties": {
          "route_id": 522,
          "name": "the Mekong",
          "tour_id": 538
        }
      }, {
        "properties": {
          "route_id": 522,
          "name": "Cambodia & the Mekong",
          "tour_id": 545
        }
      }, {
        "properties": {
          "route_id": 521,
          "name": "Cambodia",
          "tour_id": 537
        }
      }]
    };
    
    var result = {
      features: _(data.features)
        // get all routes (get rid of properties key)
        .map('properties') 
        // group by route_id
        .groupBy('route_id') 
        // place properties key again
        .map(function(group) { return { properties: group };})
        // get grouped features
        .value()
    };
      
    console.log(result);
    .as-console-wrapper{min-height:100%; top:0; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>