Categories
arrays grouping javascript

How can I group an array of objects by key?

342

Does anyone know of a way (lodash if possible too) to group an array of objects by an object key then create a new array of objects based on the grouping? For example, I have an array of car objects:

const cars = [
    {
        'make': 'audi',
        'model': 'r8',
        'year': '2012'
    }, {
        'make': 'audi',
        'model': 'rs5',
        'year': '2013'
    }, {
        'make': 'ford',
        'model': 'mustang',
        'year': '2012'
    }, {
        'make': 'ford',
        'model': 'fusion',
        'year': '2015'
    }, {
        'make': 'kia',
        'model': 'optima',
        'year': '2012'
    },
];

I want to make a new array of car objects that’s grouped by make:

const cars = {
    'audi': [
        {
            'model': 'r8',
            'year': '2012'
        }, {
            'model': 'rs5',
            'year': '2013'
        },
    ],

    'ford': [
        {
            'model': 'mustang',
            'year': '2012'
        }, {
            'model': 'fusion',
            'year': '2015'
        }
    ],

    'kia': [
        {
            'model': 'optima',
            'year': '2012'
        }
    ]
}

4

  • 2

    your result is not valid.

    Nov 23, 2016 at 21:57

  • Is there a similar approach to get a Map instead of an object?

    Apr 14, 2019 at 23:20

  • 1

    If you’re using Typescript (which is not the case of the OP) you already have groupBy method. You can use by your_array.groupBy(...)

    Aug 31, 2020 at 18:18

  • 2

    your_array.groupBy(…) doesnt exist!!

    Nov 30, 2021 at 10:27

183

Timo’s answer is how I would do it. Simple _.groupBy, and allow some duplications in the objects in the grouped structure.

However the OP also asked for the duplicate make keys to be removed. If you wanted to go all the way:

var grouped = _.mapValues(_.groupBy(cars, 'make'),
                          clist => clist.map(car => _.omit(car, 'make')));

console.log(grouped);

Yields:

{ audi:
   [ { model: 'r8', year: '2012' },
     { model: 'rs5', year: '2013' } ],
  ford:
   [ { model: 'mustang', year: '2012' },
     { model: 'fusion', year: '2015' } ],
  kia: 
   [ { model: 'optima', year: '2012' } ] 
}

If you wanted to do this using Underscore.js, note that its version of _.mapValues is called _.mapObject.

    183

    Timo’s answer is how I would do it. Simple _.groupBy, and allow some duplications in the objects in the grouped structure.

    However the OP also asked for the duplicate make keys to be removed. If you wanted to go all the way:

    var grouped = _.mapValues(_.groupBy(cars, 'make'),
                              clist => clist.map(car => _.omit(car, 'make')));
    
    console.log(grouped);
    

    Yields:

    { audi:
       [ { model: 'r8', year: '2012' },
         { model: 'rs5', year: '2013' } ],
      ford:
       [ { model: 'mustang', year: '2012' },
         { model: 'fusion', year: '2015' } ],
      kia: 
       [ { model: 'optima', year: '2012' } ] 
    }
    

    If you wanted to do this using Underscore.js, note that its version of _.mapValues is called _.mapObject.

      136

      You are looking for _.groupBy().

      Removing the property you are grouping by from the objects should be trivial if required:

      const cars = [{
        'make': 'audi',
        'model': 'r8',
        'year': '2012'
      }, {
        'make': 'audi',
        'model': 'rs5',
        'year': '2013'
      }, {
        'make': 'ford',
        'model': 'mustang',
        'year': '2012'
      }, {
        'make': 'ford',
        'model': 'fusion',
        'year': '2015'
      }, {
        'make': 'kia',
        'model': 'optima',
        'year': '2012'
      }];
      
      const grouped = _.groupBy(cars, car => car.make);
      
      console.log(grouped);
      <script src="https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js"></script>

      5

      • 33

        And if you want it shorter still, var grouped = _.groupBy(cars, 'make'); No need for a function at all, if the accessor is a simple property name.

        Nov 23, 2016 at 22:03

      • 1

        What ‘_’ stands for?

        Dec 15, 2017 at 22:40


      • @AdrianGrzywaczewski it was the default convention for name-spacing ‘lodash’ or ‘underscore’. Now that the librairies are modular it’s no longer required ie. npmjs.com/package/lodash.groupby

        – vilsbole

        Jan 17, 2018 at 15:13

      • 13

        And how can I interate in the result?

        Sep 3, 2018 at 18:03


      • I believe that would be with Object.keys(grouped)

        Apr 1, 2021 at 20:22