un par de descargos de responsabilidad clásicos primero (y un Hola a todos, porque no sé por qué sigue cortando estas 2 palabras si las pongo al principio):
Mi problema: básicamente, de un Json que contiene muchos registros en el formato {"fecha": "MM-DD-AAAA", "temperatura": entero} Estoy tratando de construir una especie de secuencia de comandos interactiva que tomará todo los diferentes meses en ese json, y automáticamente me dará la temperatura promedio para ese mes. Entonces, si cambia la matriz y agrega 1 mes de registros, inmediatamente obtengo también el nuevo promedio para el nuevo mes.
Entonces, a partir del Json, mis pasos son hacer una matriz con todos los meses incluidos en el archivo (no se incluyen todos los meses) con un mapa y una nueva fecha... luego transformaré los "meses de javascript" (que comienza desde 0... pero en el Json enero no es 0 sino 1) para hacer una serie de meses incluidos en "forma de cadena" donde Ene = "01", Feb = "02" y así sucesivamente.
Después de eso, estoy perdido: probé muchas combinaciones con bucles, bucles anidados, forEach, pero no puedo encontrar una manera de decirle a Javascript: "para cada elemento en esta matriz de meses, tome todos los registros relativos del Json, ¡y dame una temperatura promedio!"
Básicamente, lo que me gustaría lograr es simple: de un Json dado en ese formato, recupero una matriz de los meses y los resultados finales = una matriz de temperaturas promedio, 1 temperatura promedio para cada mes.
¡Intentaré publicar lo que hice hasta ahora (solo las partes que funcionan)!
¡Gracias de antemano!
const dates = [ {"date": "01-24-2020", "temps": 1}, {"date": "01-31-2020", "temps": -1}, {"date": "02-01-2020", "temps": 6}, {"date": "02-02-2020", "temps": 2}, {"date": "03-03-2020", "temps": 1}, {"date": "03-04-2020", "temps": 1}, {"date": "04-06-2020", "temps": -2}, {"date": "04-08-2020", "temps": -4}] const singleMonths = Array.from(new Set(dates.map(elem => new Date(elem.date).getMonth()))) const singleMonthString = singleMonths.map(m => `${"0"+(m+1)}`) //after this I tried A LOT of different solutions, but I can only filter manually for a singular item in my Array, and not how I would like to, automatically for all my items in my array! const damnFilter = dates.filter(m => m.dates.substring(0,2)==result[0])No sé si es lo que quieres, pero aquí creé algunos de los fragmentos, donde obtiene cuatro meses y promedia la temperatura de cada mes:
let newDates = []; for(let i = 1; i <= 12; i++){ newDates = dates.filter(date => new Date(date.date).getMonth() + 1 == i) if(newDates.length > 0){ let accumulator = 0; newDates.map(day => accumulator += day.temps); console.log("Average: ", accumulator / newDates.length); } }Algunos comentarios sobre su código:
const singleMonths = Array.from(new Set(dates.map(elem => new Date(elem.date).getMonth())))
es bastante ineficiente. Los datos ya son una matriz, no es necesario crear una nueva matriz a través de map , convertirla en un conjunto y luego volver a otra matriz. Además, no hay necesidad de crear una Fecha para obtener el mes, sin mencionar la ineficiencia de hacer el +1 a través de otro mapa cuando podría hacerse en la línea de arriba (si fuera necesario).
ECMAScript no admite el formato dd-mm-yyyy, por lo que el análisis depende de la implementación. Safari al menos lo trata como una fecha no válida, consulte ¿Por qué Date.parse da resultados incorrectos?
const singleMonthString = singleMonths.map(m => `${"0"+(m+1)}`)
Si se necesitaba el +1, mejor hacerlo en el primer mapa, e incluso si necesita hacerlo, ¿por qué crear otra matriz? Simplemente use forEach y modifique la matriz existente.
const damnFilter = dates.filter(m => m.dates.substring(0,2)==result[0])
El resultado no se declara ni se inicializa en ninguna parte, por lo que no va a ninguna parte.
Puede usar reduce en la matriz de datos para sumar las temperaturas de un mes en particular y generar un promedio. Es conveniente mantener los valores de sum y count durante un mes en el acumulador que se pasa a cada bucle posterior. Luego puede generar un nuevo promedio cada vez o hacerlo al final. Calcular el promedio cada vez es más simple pero posiblemente menos eficiente si el archivo de datos es grande. Pero para un archivo pequeño la diferencia será insignificante.
let data = [ {"date": "01-24-2020", "temps": 1}, {"date": "01-31-2020", "temps": -1}, {"date": "02-01-2020", "temps": 6}, {"date": "02-02-2020", "temps": 2}, {"date": "03-03-2020", "temps": 1}, {"date": "03-04-2020", "temps": 1}, {"date": "04-06-2020", "temps": -2}, {"date": "04-08-2020", "temps": -4} ]; let averageData = data.reduce((acc, obj) => { // Get month number let month = obj.date.slice(0,2); // If accumulator doesn't have a summary object for // that month, add it with initial values if (!acc[month]) { acc[month] = {sum:0, count:0, year: obj.date.slice(-4)}; } // Update summary values for the month acc[month].sum += obj.temps; acc[month].count += 1; acc[month].average = acc[month].sum / acc[month].count; // Return the accumulator return acc; // Use a completely emtpy object for the accumulator }, Object.create(null)); // Show averageData object console.log(averageData); // Show data as month : average Object.keys(averageData).forEach(key => console.log( new Date(averageData[key].year, key-1).toLocaleString('en',{month:'short', year:'numeric'}) + ': ' + averageData[key].average ));