Tengo esta matriz:
[{start_date: "2022-12-05T04:00:00Z" ,distance: 1000, time: 3600} ,{start_date: "2022-02-07T04:00:00Z" ,distance: 1500, time: 6400}, {start_date: "2022-12-08T04:00:00Z" ,distance: 1000, time: 1300}]Quiero agregar los valores de distancia y tiempo agrupándolos por el mes que indica el valor start_date. Por ejemplo, si dos start_dates tienen el mismo mes 2022-12-01 y 2022-12-08, ¿cómo puedo sumar los valores de distancia y tiempo de esos dos meses?
entonces obtengo una nueva matriz como esta:
[{month: 12 ,total distance: 2000, total time: 4900}, {month: 02 , total distance: 1500, total time: 6400} ]puede usar reduce para agruparlos por mes, lo que dará un objeto como
{ 12: { distance: 2000, month: 12, time: 4900 }, 2: { distance: 1500, month: 2, time: 6400 } } y usando Object.values obtener la matriz de valores de la misma
let x = [{start_date: "2022-12-05T04:00:00Z" ,distance: 1000, time: 3600},{start_date: "2022-02-07T04:00:00Z" ,distance: 1500, time: 6400},{start_date: "2022-12-08T04:00:00Z" ,distance: 1000, time: 1300}] let res = Object.values(x.reduce((acc,{start_date,distance,time})=> { let month = new Date(start_date).getMonth()+1 if(!acc[month])acc[month] = {totalDistance:0,totalTime:0,month:month} acc[month].totalDistance+=distance acc[month].totalTime+=time return acc; },{})) console.log(res)Puede usar un objeto como diccionario y guardar un valor acumulado de tiempo y distancia por clave de mes. Luego, reduzca todas las claves a una matriz con el formato solicitado.
const groupPerMonth = (list) => { const extractMonth = (stringDate) => { const month = new Date(stringDate).getMonth() + 1; return month < 10 ? `0${month}` : `${month}`; } const months = {}; for (const item of list) { const month = extractMonth(item.start_date); if (!(month in months)) { months[month] = { distance: 0, total_time: 0, }; } months[month].distance += item.distance; months[month].total_time += item.time; } const result = []; for (const month in months) { result.push({ month, ...months[month] }); } return result; };Y pruébalo:
console.log( groupPerMonth([ { start_date: "2022-12-05T04:00:00Z", distance: 1000, time: 3600 }, { start_date: "2022-02-07T04:00:00Z", distance: 1500, time: 6400 }, { start_date: "2022-12-08T04:00:00Z", distance: 1000, time: 1300 }, ]) );Producción:
[ { month: '12', distance: 2000, total_time: 4900 }, { month: '02', distance: 1500, total_time: 6400 } ]Puede haber diferentes soluciones para esto, pero una forma de resolverlo es usar la biblioteca lodash para resolverlo. Primero podemos group por mes, luego mapping cada elemento agrupado y agregar los valores de distancia y tiempo en cada grupo usando reduce :
const list = [ {start_date: "2022-12-05T04:00:00Z" ,distance: 1000, time: 3600}, {start_date: "2022-02-07T04:00:00Z" ,distance: 1500, time: 6400}, {start_date: "2022-12-08T04:00:00Z" ,distance: 1000, time: 1300} ] const grouped = _.groupBy(list, item => { const date = new Date(item.start_date) return date.getMonth() + 1 }) const groupedAndMapped = _.map(grouped, function(groupedList, date){ return { month: date, total_distance: _.reduce(groupedList, (total, current) => { return total + current.distance }, 0), total_time:_.reduce(groupedList, (total, current) => { return total + current.time }, 0) } }) Una mejora que podría hacer es formatear el mes en un formato "MM-YYYY" o algo similar, ya que es posible que su conjunto de datos pueda incluir elementos con diferentes años.