Home > front end >  Count re structure based on month/week/year
Count re structure based on month/week/year

Time:07-26

I have an array like this (count and date)

day = [
  { count: 1, date: '2022-07-07' },
  { count: 1, date: '2022-08-14' },
  { count: 2, date: '2022-07-19' },
  { count: 4, date: '2022-07-19' },
  { count: 2, date: '2021-01-19' },
  { count: 2, date: '2021-03-02' }
]

now I am looking for a new array, it should be total count week/month/year base

I am expecting like this below

 month = [
      { count: 7, date: '2022-07-01' },
      { count: 1, date: '2022-08-01' },
      { count: 2, date: '2021-01-01' },
      { count: 2, date: '2021-03-01' }
    ]
    year = [
      { count: 9, date: '2022-01-01' },
      { count: 4, date: '2021-01-01' },
    ]

Same like week bases as well

I am trying to achieve something like this

let month;
for( d of day ) {
    if(condition) {
     // calculation for count adding 
     month.push(d)
   }
}

CodePudding user response:

Updated the answer based on RobG suggestions.

I didn't implement the groupByWeek() part, but the implementation of this part should be similar to groupByMonth() and groupByYear() function in below code.

For the groupByWeek part, the tricky part is how to get the week number of the date, I think the getWeek() function from cmgchess shared codes in the above comment section would be helpful, or you can use a date library to get the week number.

    let day = [
        { count: 1, date: "2022-07-07" },
        { count: 1, date: "2022-08-14" },
        { count: 2, date: "2022-07-19" },
        { count: 4, date: "2022-07-19" },
        { count: 2, date: "2021-01-19" },
        { count: 2, date: "2021-03-02" },
        { count: 5, date: "2021-07-19" },
    ];
    
    // create a map of {$year-$month-01: $count} based on the data in day array
    let groupByMonth = day.reduce((partialCount, item) => {
        let dateSplit = item.date.split("-");
        let y = dateSplit[0];
        let m = dateSplit[1];
        if (Object.prototype.hasOwnProperty.call(partialCount, `${y}-${m}-01`)) {
            partialCount[`${y}-${m}-01`]  = item.count;
        } else {
            partialCount[`${y}-${m}-01`] = item.count;
        }
        return partialCount;
    }, {});
    
    // convert the groupByMonth map into an array of object(your expected format)
    let monthList = Object.keys(groupByMonth).map(key => {
        return {
            count: groupByMonth[key],
            date: key
        };
    });
    
    // create a map of {$year-01-01: $count} based on the data in day array
    let groupByYear = day.reduce((partialCount, item) => {
        let dateSplit = item.date.split("-");
        let y = dateSplit[0];
        if (Object.prototype.hasOwnProperty.call(partialCount, `${y}-01-01`)) {
            partialCount[`${y}-01-01`]  = item.count;
        } else {
            partialCount[`${y}-01-01`] = item.count;
        }
        return partialCount;
    }, {});

    // convert the groupByMonth map into an array of object(your expected format)
    let yearList = Object.keys(groupByYear).map(key => {
        return {
            count: groupByYear[key],
            date: key
        };
    });
    
    console.log("month:", monthList);
    console.log("year:", yearList);

CodePudding user response:

I implemeted a solution that return an object with :

key => value = month / year => totalCount

I hope the output is okay for your, it lookes more logical to me than use only one date of the month / year to name it. By the way I can change the output format if it is a problem or you ;)

Here is the code :

const toArray = obj => Object.keys(obj).map(k => [k, obj[k]]); // transform an object to array of array [[key], [value]];

const sum = arr => arr.reduce((ps, a) => ps   a, 0); // sum an array

let day = [
    { count: 1, date: '2022-07-07' },
    { count: 1, date: '2022-08-14' },
    { count: 2, date: '2022-07-19' },
    { count: 4, date: '2022-07-19' },
    { count: 2, date: '2021-01-19' },
    { count: 2, date: '2021-03-02' }
];

let years = Object.fromEntries( // transform the result to an object 
    toArray( // transform the object to array
        day.reduce((acc, x) => { // sort the day by month / year
            // key (month or year) doesn't exist => create the key => append the element
            (acc[x.date.split('-').at(0)] = acc[x.date.split('-').at(0)] || []).push(x.count);
            return acc;
        }, {})
    ).map(arr => [arr.at(0), sum(arr.at(1))]) // sum the counts
);

let months = Object.fromEntries(toArray(day.reduce((acc, x) => {
    (acc[x.date.split('-').at(1)] = acc[x.date.split('-').at(1)] || []).push(x.count);
    return acc;
}, {})).map(arr => [arr.at(0), sum(arr.at(1))]));

console.log(months);
console.log(years);

  • Related