简体   繁体   中英

How to add the values ​in an array of objects depending on the date value of each object

I have this array:

[{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}]

I want to add the distance and time values grouping them by the month indicated by the start_date value. For example, if two start_dates have the same month 2022-12-01 and 2022-12-08, how can I add the distance and time values of those two months?

so i get a new array like this:

 [{month: 12 ,total distance: 2000, total time: 4900}, 
  {month: 02 , total distance: 1500, total time: 6400} ]

you can use reduce to group them by month which will give an object like

{
  12: {
    distance: 2000,
    month: 12,
    time: 4900
  },
  2: {
    distance: 1500,
    month: 2,
    time: 6400
  }
}

and using Object.values get the values array of it

 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)

You can use a object as a dictionary and save a accumulated value of time and distance per month key. Then, reduce all keys to an array with the requested format.

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;
};

And test it:

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 },
  ])
);

Output:

[
  { month: '12', distance: 2000, total_time: 4900 },
  { month: '02', distance: 1500, total_time: 6400 }
]

There might be different solutions to this, but one way to solve this is by using the lodash library to solve this. We can first group by month, followed by mapping each grouped item and adding the distance and time values in each group using 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)
    }
})

One improvement you could do is to format the month to an "MM-YYYY" format or something similar as its possible your data set can include items with different years.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM