¿Cómo podemos agrupar objetos de matriz por propiedades? Por ejemplo, a continuación, quiero agrupar los datos de muestra por su oldStockBooks.name (vea el resultado esperado en la parte inferior).
He estado en los siguientes enlaces, pero no puedo aplicarlo en mi escenario stack-link-1 , stack-link-2 .
He probado estos códigos a continuación, pero no funciona según lo previsto.
var counter = {}; oldStockBooks.forEach(function(obj) { var key = JSON.stringify(obj) counter[key] = (counter[key] || 0) + 1 });Data de muestra:
const oldStockBooks = [ { name: 'english book', author: 'cupello', version: 1, //... more props here }, { name: 'biology book', author: 'nagazumi', version: 4, }, { name: 'english book', author: 'cupello', version: 2, }, ]; Resultado esperado: mostrar solo el name , el author y total accesorios. Y total props sería el número de duplicados por nombre de libro.
const output = [ { name: 'english book', author: 'cupello', total: 2, }, { name: 'biology book', author: 'nagazumi', total: 1, }, ];Puedes usar reduce en tus oldStockBooks para construir un objeto Map . Dado que desea agrupar por name , las claves en el objeto Mapa pueden ser los valores de name de sus objetos. Al crear su Mapa, si encuentra un nombre que ya está en su Mapa, puede tomar el total del objeto almacenado en esa clave y crear un nuevo objeto con un total actualizado. De lo contrario, si aún no ha visto el objeto, puede establecer el total en 0 (hecho mediante la desestructuración con un valor predeterminado: total = 0 ). Una vez que tenga su Mapa, puede tomar los objetos de valor de él y convertirlos en una matriz con Array.from() :
const oldStockBooks = [{ name: 'english book', author: 'cupello', version: 1, }, { name: 'biology book', author: 'nagazumi', version: 4, }, { name: 'english book', author: 'cupello', version: 2, }, ]; const res = Array.from(oldStockBooks.reduce((acc, obj) => { // Grab name, author and total keys from the seen object. If the object hasn't already been seen, use the current object to grab the name and author, and default the total to 0 const {name, author, total=0} = acc.get(obj.name) || obj; return acc.set(obj.name, {name, author, total: total+1}); // update the total }, new Map).values()); console.log(res);Puede lograr el resultado de manera eficiente utilizando Map
const oldStockBooks = [ { name: "english book", author: "cupello", version: 1, }, { name: "biology book", author: "nagazumi", version: 4, }, { name: "english book", author: "cupello", version: 2, }, ]; const map = new Map(); oldStockBooks.forEach(({ name, author }) => map.has(name) ? (map.get(name).total += 1) : map.set(name, { name, author, total: 1 }) ); const result = [...map.values()]; console.log(result);Estás cerca de la respuesta:
var response = {}; // here we put the itens mapped by the key (the 'name' field) oldStockBooks.forEach(function(obj) { if( !response[ obj.name ] ) { // if it is the first item of this 'name' response[ obj.name ] = { name: obj.name, author: obj.author, total: 1, }; } else { // else, we have one already, so lets only increment the total count response[ obj.name ].total += 1; } }); // if need a list/array var myBooks = []; for(var key in response) myBooks.push( response[key] );