Tengo un conjunto de datos que estoy tratando de convertir en una estructura diferente. Casi he alcanzado el requisito, pero estoy atascado en la última parte. Aquí está el código y lo que he intentado hasta ahora.
let array1 = [ { aggr_type: "mean", date: ['19 Apr', '20 Apr'], mean: [13.87, 8.42], name: "TEMPERATURE", sum: [0.1, 0.2] }, { aggr_type: "sum", date: ['19 Apr', '20 Apr'], mean: [45.42, 55.22], name: "HUMIDITY", sum: [0.3, 0.5] } ]; let names = []; array1.forEach(el => { names.push(el.name); }); const myObj = names.reduce((a, key) => Object.assign(a, { [key]: null, date: null }), {}); // console.log(myObj); // console.log(array1); let arrays = [] for(i=0; i < array1[0].date.length; i++) { array1.forEach(el => { myObj.date = el.date[i]; myObj[el.name] = el.[el.aggr_type][i]; arrays.push(myObj); }); } console.log(arrays);Si este fragmento no funciona, use este codepen
Se supone que debo tener la salida como esta.
[ { 'TEMPERATURE': '13.87', 'date': '19 Apr', 'HUMIDITY': '0.3' }, { 'TEMPERATURE': '8.42', 'date': '20 Apr', 'HUMIDITY': '0.5' } ];Pero solo devuelve el último índice. ¿Hay alguna forma de obtener el resultado como lo mencioné anteriormente?
NOTA: Los valores deben agregarse al resultado final en función de aggr_type
La siguiente puede ser una posible solución para lograr el objetivo deseado.
Fragmento de código
// method to obtain the desired objective const groupByDate = arr => ( Object.values( // extract only the "values" from result of "reduce" arr.reduce( // use "reduce" to iterate over the array (acc, {name, date, mean}) => { date.forEach( // for each "date" in the "date-array" (d, i) => { // populate / update the "acc" (accumulator) acc[d] = { ...(acc[d] || {}), [name]: mean[i], // this line populates either temperator or humidity date: d, } } ) return acc; // always return the "acc" }, {} // initially the "acc" is set as an empty object ) ) ); let array1 = [ { aggr_type: "mean", date: ['19 Apr', '20 Apr'], mean: [13.87, 8.42], name: "TEMPERATURE", sum: [0.1, 0.2] }, { aggr_type: "sum", date: ['19 Apr', '20 Apr'], mean: [45.42, 55.22], name: "HUMIDITY", sum: [0.3, 0.5] } ]; console.log(groupByDate(array1));Explicación Los comentarios en línea en el fragmento anterior explican los aspectos importantes.
EDITAR
Usó la matriz de entrada array1 que se actualizó en la pregunta. La respuesta del fragmento coincide con la matriz esperada en la pregunta:
[ { 'TEMPERATURE': '13.87', 'date': '19 Apr', 'HUMIDITY': '45.42' }, { 'TEMPERATURE': '8.42', 'date': '20 Apr', 'HUMIDITY': '55.22' } ];EDITAR 2
// method to obtain the desired objective const groupByDate = arr => ( Object.values( // extract only the "values" from result of "reduce" arr.reduce( // use "reduce" to iterate over the array (acc, ob) => { const {name, date, aggr_type} = ob; const tgt = ob[aggr_type]; // decide whether to use "mean" or "sum" date.forEach( // for each "date" in the "date-array" (d, i) => { // populate / update the "acc" (accumulator) acc[d] = { ...(acc[d] || {}), [name]: tgt[i], // this line populates either temperature or humidity date: d, } } ) return acc; // always return the "acc" }, {} // initially the "acc" is set as an empty object ) ) ); let array1 = [ { aggr_type: "mean", date: ['19 Apr', '20 Apr'], mean: [13.87, 8.42], name: "TEMPERATURE", sum: [0.1, 0.2] }, { aggr_type: "sum", date: ['19 Apr', '20 Apr'], mean: [45.42, 55.22], name: "HUMIDITY", sum: [0.3, 0.5] } ]; console.log(groupByDate(array1));El problema es que ha creado un solo myObj
const myObj = names.reduce((a, key) => Object.assign(a, { [key]: null, date: null }), {});y lo asignas y luego lo empujas dentro de tu ciclo
for (i=0; i < array1[0].date.length; i++) { array1.forEach(el => { myObj.date = el.date[i]; // <-- modifies the ONE 'myObj' myObj[el.name] = el.[el.aggr_type][i]; arrays.push(myObj); // <-- pushes the ONE myObj (again) }); } Termina con 4 referencias a myObj en sus arrays : cada vez que lo asigna, por ejemplo, myObj.date = el.date[i] , está modificando ese único myObj ... Es decir, después de la primera vez haces arrays.push(myObj) tienes arrays[0] que contienen myObj , luego la próxima vez a través del ciclo cuando asignas valores a myObj nuevamente, eso está cambiando los valores que están en arrays[0] ya que ese es myObj .
Puede tratar myObj como un prototipo : necesita instancias separadas de objetos que se parezcan a myObj para que cada uno insertado en arrays sea un objeto único.
Modificando su código original lo menos posible, aquí hay una forma de hacerlo:
let array1 = [ { aggr_type: "mean", date: ['19 Apr', '20 Apr'], mean: [13.87, 8.42], name: "TEMPERATURE", }, { aggr_type: "mean1", date: ['19 Apr', '20 Apr'], mean: [45.42, 55.22], name: "HUMIDITY", } ]; let names = []; array1.forEach(el => { names.push(el.name); }); // Changed the name here so I wouldn't have to change it in the loop const protoMyObj = names.reduce((a, key) => Object.assign(a, { [key]: null, date: null }), {}); // console.log(myObj); // console.log(array1); let arrays = [] for (i=0; i < array1[0].date.length; i++) { array1.forEach(el => { // Make a new copy of the "prototype" `protoMyObj` let myObj = Object.assign({}, protoMyObj); myObj.date = el.date[i]; myObj[el.name] = el.mean[i]; arrays.push(myObj); }); } console.log(arrays);