Digamos que tengo la siguiente matriz JSON:
[ { "name": "x", "category": "y", "attributes": { "name": "a", "description": "b" } }, { "name": "x", "category": "y", "attributes": { "name": "c", "description": "d" } } ]¿Cómo puedo combinar los elementos donde cada propiedad es idéntica, pero agregar las diferentes propiedades a una matriz anidada?
[ { "name": "x", "category": "y", "attributes": [ { "name": "a", "description": "b" }, { "name": "c", "description": "d" } ] } ]Para ser más específicos, cualquier elemento diferente debe agregarse a la matriz; por ejemplo, si el atributo con el nombre "c" tuviera la descripción "b", aún querría que el atributo completo se agregue a la lista de "atributos".
No he podido encontrar este problema en StackOverflow a través de una búsqueda exhaustiva. ¡Aprecio tu ayuda!
Pude modificar ligeramente mis entradas para lograr una solución (tengo un conocimiento limitado de JS). Las nuevas entradas son:
const myJson = [{ "name": "x", "category": "y", "attributes": { "name": "a", "description": "b" } }, { "attributes": { "name": "c", "description": "d" } }, { "category": "z" } ]Ahora puedo recorrer los elementos (en orden). Si un elemento carece de la "clave maestra" (en este caso, "nombre"), agregaré esa clave/valor al último elemento con la clave maestra o crearé una lista de valores y la agregaré.
function mergeObjects_(objects) { var result = []; const masterKey = 'name'; for (let i = 0; i < objects.length; i++) { let object = objects[i]; if (object.hasOwnProperty(masterKey)) { result.push(object); } else { for (const [key, value] of Object.entries(object)) { if (Array.isArray(result[result.length - 1][key])) { result[result.length - 1][key].push(value); } else { var attribute_arr = [result[result.length - 1][key]]; attribute_arr.push(value); result[result.length - 1][key] = attribute_arr; } } } } return result; }Esto contrae la muestra a la siguiente y funciona en varios elementos
[ { "name": "x", "category": [ "y", "z" ], "attributes": [ { "name": "a", "description": "b" }, { "name": "c", "description": "d" } ] } ]Por supuesto, esto supone que existe una de las propiedades finales en el objeto con la clave maestra. Para mis propósitos, está bien dada la forma en que se generan los datos. Gracias a todos por sus respuestas y ayuda!
La forma más sencilla es usar la función de reducción
const data = [ { name: 'x', category: 'y', attributes: { name: 'a', description: 'b', }, }, { name: 'x', category: 'y', attributes: { name: 'c', description: 'd', }, }, ]; const answer = data.reduce((result, current) => { const findIndex = result.findIndex((item) => item.name === current.name); // if the name does not exist in the result, append it to the result array if (findIndex === -1) { return [ ...result, { name: current.name, category: current.category, attributes: [current.attributes], }, ]; } return result.map((value, index) => { if (index === findIndex) { value.attributes.push(current.attributes); } return value; }); }, []); console.log(answer);//It's very simple and best for huge data var arr = [ { "name": "x", "category": "y", "attributes": { "name": "a", "description": "b" } }, { "name": "x", "category": "y", "attributes": { "name": "c", "description": "d" } } ]; var newArr = []; var objKeyValue = {}; arr.forEach(rec => { if (objKeyValue[rec.name + rec.category]) objKeyValue[rec.name + rec.category].attributes.push(rec.attributes); else objKeyValue[rec.name + rec.category] = { name: rec.name, category: rec.category, attributes: [rec.attributes] }; }); console.log("Output", Object.values(objKeyValue));