Come raggruppare un array di oggetti per chiave

Qualcuno sa di un modo (lodash se ansible) per raggruppare una serie di oggetti con una chiave object e quindi creare una nuova matrice di oggetti basata sul raggruppamento? Ad esempio, ho una serie di oggetti auto:

var 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' }, ]; 

Voglio creare una nuova serie di oggetti auto raggruppati per make :

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

La risposta di Timo è come lo farei. Semplice _.groupBy e consente alcune duplicazioni negli oggetti nella struttura raggruppata.

Tuttavia, l’OP ha chiesto anche la rimozione delle chiavi duplicate. Se volessi andare fino in fondo:

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

I rendimenti:

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

Se vuoi farlo utilizzando Underscore.js, nota che la sua versione di _.mapValues è chiamata _.mapObject .

In semplice Javascript, è ansible utilizzare la Array#reduce con un object

 var 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' }], result = cars.reduce(function (r, a) { r[a.make] = r[a.make] || []; r[a.make].push(a); return r; }, Object.create(null)); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Stai cercando _.groupBy() .

Rimuovere la proprietà che stai raggruppando dagli oggetti dovrebbe essere banale se necessario:

 var 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'},]; var grouped = _.groupBy(cars, function(car) { return car.make; }); console.log(grouped); 
  

La versione breve di es6:

 result = cars.reduce((h, a) => Object.assign(h, { [a.make]:( h[a.make] || [] ).concat(a) }), {}) 

Puoi provare a modificare l’object all’interno della funzione chiamata per iterazione da _.groupBy func. Si noti che l’array sorgente cambia i suoi elementi!

 var res = _.groupBy(cars,(car)=>{ const makeValue=car.make; delete car.make; return makeValue; }) console.log(res); console.log(cars); 

Ecco la tua propria funzione groupBy che è una generalizzazione del codice da: https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

 function groupBy(xs, f) { return xs.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), {}); } 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 result = groupBy(cars, (c) => c.make); console.log(result); 

È anche ansible con un ciclo for semplice:

  const result = {}; for(const {make, model, year} of cars) { if(!result[make]) result[make] = []; result[make].push({ model, year }); } 

Puoi anche usare il metodo array#forEach() questo modo:

 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' }]; let newcars = {} cars.forEach(car => { newcars[car.make] ? // check if that array exists or not in newcars object newcars[car.make].push({model: car.model, year: car.year}) // just push : (newcars[car.make] = [], newcars[car.make].push({model: car.model, year: car.year})) // create a new array and push }) console.log(newcars);