recorrer objetos matriz dinamico declarar con claves asociativos asociativo array agrupar agregar javascript arrays object grouping lodash

javascript - dinamico - Cómo agrupar una matriz de objetos por clave



matriz javascript (18)

Aquí está su propia función groupBy , que es una generalización del código de: 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);

¿Alguien sabe de una manera (lodash si es posible también) de agrupar una matriz de objetos por una clave de objeto y luego crear una nueva matriz de objetos basada en la agrupación? Por ejemplo, tengo una variedad de objetos de automóviles:

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

Quiero hacer una nueva matriz de objetos de automóviles que se agrupen por 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'' } ] }


Con lodash / fp puede crear una función con _.flow() que primero agrupa por una tecla, y luego _.flow() cada grupo y omite una tecla de cada elemento:

const { flow, groupBy, mapValues, map, omit } = _; const groupAndOmitBy = key => flow( groupBy(key), mapValues(map(omit(key))) ); 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 groupAndOmitMake = groupAndOmitBy(''make''); const result = groupAndOmitMake(cars); console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }

<script src=''https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)''></script>


Cree un método que pueda reutilizarse

Array.prototype.groupBy = function(prop) { return this.reduce(function(groups, item) { const val = item[prop] groups[val] = groups[val] || [] groups[val].push(item) return groups }, {}) };

A continuación, puede agrupar por cualquier criterio

const groupByMake = cars.groupBy(''make''); console.log(groupByMake);

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'' }, ]; //re-usable method Array.prototype.groupBy = function(prop) { return this.reduce(function(groups, item) { const val = item[prop] groups[val] = groups[val] || [] groups[val].push(item) return groups }, {}) }; // initiate your groupBy. Notice the recordset Cars and the field Make.... const groupByMake = cars.groupBy(''make''); console.log(groupByMake); //At this point we have objects. You can use Object.keys to return an array


Dejaría REAL GROUP BY para el ejemplo de JS Arrays exactamente la misma tarea here

const inputArray = [ { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" }, { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" } ]; var outObject = inputArray.reduce(function(a, e) { // GROUP BY estimated key (estKey), well, may be a just plain key // a -- Accumulator result object // e -- sequentally checked Element, the Element that is tested just at this itaration // new grouping name may be calculated, but must be based on real value of real field let estKey = (e[''Phase'']); (a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e); return a; }, {}); console.log(outObject);

Да здравствуют высокие показатели мастерства программистов во имя процветания всего человечества! Ура, товарищи!


En Javascript simple, puede usar Array#reduce con un objeto

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; }


La versión corta para agrupar una matriz de objetos por una determinada clave en es6:

result = array.reduce((h, obj) => Object.assign(h, { [obj.key]:( h[obj.key] || [] ).concat(obj) }), {})

La versión más larga:

result = array.reduce(function(h, obj) { h[obj.key] = (h[obj.key] || []).concat(obj); return h; }, {})

Parece que la pregunta original pregunta cómo agrupar los automóviles por marca, pero omita la marca en cada grupo. Entonces la respuesta se vería así:

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


Me gustó la respuesta @metakunfu, pero no proporciona exactamente la salida esperada. Aquí hay una actualización que elimina "make" en la carga útil final de JSON.

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((h, car) => Object.assign(h, { [car.make]:( h[car.make] || [] ).concat({model: car.model, year: car.year}) }), {}) console.log(JSON.stringify(result));

Salida:

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


Para casos donde la clave puede ser nula y queremos agruparlos como otros

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''}, {''make'':''kia'',''model'':''optima'',''year'':''2033''}, {''make'':null,''model'':''zen'',''year'':''2012''}, {''make'':null,''model'':''blue'',''year'':''2017''}, ]; result = cars.reduce(function (r, a) { key = a.make || ''others''; r[key] = r[key] || []; r[key].push(a); return r; }, Object.create(null));


Puede intentar modificar el objeto dentro de la función llamada por iteración por _.groupBy func. ¡Observe que la matriz fuente cambia sus elementos!

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


Sobre la base de la answer de @Jonas_Wilms si no desea escribir en todos sus campos:

var result = {}; for ( let { first_field, ...fields } of your_data ) { result[first_field] = result[first_field] || []; result[first_field].push({ ...fields }); }

No hice ningún punto de referencia, pero creo que usar un bucle for también sería más eficiente que cualquier cosa sugerida en esta respuesta .


Solo prueba este, me funciona bien.

let grouped = _.groupBy(cars, ''make'');


También es posible con un bucle for simple:

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


También puede hacer uso del método array#forEach() esta manera:

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);


La respuesta de Timo es cómo lo haría. Simple _.groupBy , y permite algunas duplicaciones en los objetos en la estructura agrupada.

Sin embargo, el OP también solicitó la eliminación de las claves duplicadas. Si quisieras ir hasta el final:

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

Rendimientos:

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

Si desea hacer esto usando Underscore.js, tenga en cuenta que su versión de _.mapValues se llama _.mapObject .


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'' }].reduce((r, a) => { const { model, year } = a; r[a.make] = [...r[a.make] || [], { model, year }]; return r; }, {}); console.log(cars);


Estás buscando _.groupBy() .

Eliminar la propiedad por la que está agrupando los objetos debería ser trivial si es necesario:

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);

<script src=''https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js''></script>

Como beneficio adicional, obtienes una sintaxis aún mejor con las funciones de flecha ES6:

const grouped = _.groupBy(cars, car => car.make);


const reGroup = (list, key) => { const newGroup = {}; list.forEach(item => { const newItem = Object.assign({}, item); delete newItem[key]; newGroup[item[key]] = newGroup[item[key]] || []; newGroup[item[key]].push(newItem); }); return newGroup; };

const animals = [ { type: ''dog'', breed: ''puddle'' }, { type: ''dog'', breed: ''labradoodle'' }, { type: ''cat'', breed: ''siamese'' }, { type: ''dog'', breed: ''french bulldog'' }, { type: ''cat'', breed: ''mud'' } ]; console.log(reGroup(animals, ''type''));

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'' }, ]; console.log(reGroup(cars, ''make''));


function groupBy(data, property) { return data.reduce((acc, obj) => { const key = obj[property]; if (!acc[key]) { acc[key] = []; } acc[key].push(obj); return acc; }, {}); } groupBy(people, ''age'');