最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to group array of dates by month and year - Stack Overflow

programmeradmin0浏览0评论

Hi I'm having an array of the date object

  "["2021-01-05T06:30:00.000Z","2021-01-06T06:30:00.000Z",
    "2021-01-20T06:30:00.000Z","2021-02-09T06:30:00.000Z",
    "2021-02-23T06:30:00.000Z","2021-02-16T06:30:00.000Z",
    "2020-12-08T06:30:00.000Z","2020-12-15T06:30:00.000Z",
    "2020-12-02T06:30:00.000Z","2020-12-09T06:30:00.000Z",
    "2020-12-16T06:30:00.000Z"]"

I need to format into this

[
  {
    "month": "12",
    "year": "2020",
    "dates": [1,14,25]
  },
  {
    "month": "10",
    "year": "2020",
    "dates": [1]
  }
]

How to format like this help me. I have done like this but not pleted I was stuck in adding dates. I know this is not the correct way of doing it. Please don't bother the code I have written I know it's garbage.

dateArray.reduce((initial,next)=>{
   let result=[]    
   if(isSameYear(new Date(initial),new Date(next) && 
      isSameMonth(new Date(initial),new Date(next))){
         result.push({
                 month:new Date(nex).getMonth(), 
                  year: new Date(next).getFullYear 
         })
    }
})

Hi I'm having an array of the date object

  "["2021-01-05T06:30:00.000Z","2021-01-06T06:30:00.000Z",
    "2021-01-20T06:30:00.000Z","2021-02-09T06:30:00.000Z",
    "2021-02-23T06:30:00.000Z","2021-02-16T06:30:00.000Z",
    "2020-12-08T06:30:00.000Z","2020-12-15T06:30:00.000Z",
    "2020-12-02T06:30:00.000Z","2020-12-09T06:30:00.000Z",
    "2020-12-16T06:30:00.000Z"]"

I need to format into this

[
  {
    "month": "12",
    "year": "2020",
    "dates": [1,14,25]
  },
  {
    "month": "10",
    "year": "2020",
    "dates": [1]
  }
]

How to format like this help me. I have done like this but not pleted I was stuck in adding dates. I know this is not the correct way of doing it. Please don't bother the code I have written I know it's garbage.

dateArray.reduce((initial,next)=>{
   let result=[]    
   if(isSameYear(new Date(initial),new Date(next) && 
      isSameMonth(new Date(initial),new Date(next))){
         result.push({
                 month:new Date(nex).getMonth(), 
                  year: new Date(next).getFullYear 
         })
    }
})
Share edited Jan 12, 2021 at 5:24 Not A Robot 2,6922 gold badges19 silver badges37 bronze badges asked Jan 12, 2021 at 5:13 SukeshSukesh 1971 gold badge4 silver badges15 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 2

maybe do it in two passes

const dateArray = ["2021-01-05T06:30:00.000Z", "2021-01-06T06:30:00.000Z", "2021-01-20T06:30:00.000Z", "2021-02-09T06:30:00.000Z", "2021-02-23T06:30:00.000Z", "2021-02-16T06:30:00.000Z", "2020-12-08T06:30:00.000Z", "2020-12-15T06:30:00.000Z", "2020-12-02T06:30:00.000Z", "2020-12-09T06:30:00.000Z", "2020-12-16T06:30:00.000Z"];


const mapping = dateArray.reduce((initial, next) => {
  const month = next.substring(5, 7);
  const year = next.substring(0, 4);
  const day = next.substring(8, 10);

  initial[year] = initial[year] || {};
  initial[year][month] = initial[year][month] || [];
  initial[year][month].push(parseInt(day, 10));
  return initial;
}, {});

const result = []
Object.keys(mapping).forEach(year => {
  Object.keys(mapping[year]).forEach(month => {
    result.push({
      month,
      year,
      dates: mapping[year][month]
    });
  });
});

console.log(result);

You can group dates based on year and month in an object accumulator.

const data = ["2021-01-05T06:30:00.000Z", "2021-01-06T06:30:00.000Z", "2021-01-20T06:30:00.000Z", "2021-02-09T06:30:00.000Z", "2021-02-23T06:30:00.000Z", "2021-02-16T06:30:00.000Z", "2020-12-08T06:30:00.000Z", "2020-12-15T06:30:00.000Z", "2020-12-02T06:30:00.000Z", "2020-12-09T06:30:00.000Z", "2020-12-16T06:30:00.000Z" ],
      result = Object.values(data.reduce((r, date) => {
        const [year, month, day] = date.substr(0,10).split('-');
        const key = `${year}_${month}`;
        r[key] = r[key] || {month, year, dates: []};
        r[key].dates.push(day);
        return r;
      },{}));
console.log(result);

When you group things in general, it's easier to group them into an object. The reason is you don't have to search an array for a matching result to append to, you only have to look up a key to concatenate to.

Here's one solution that builds an object, grouped by string keys built out of the month and year, and then maps over the values of that object to build the array you're looking for, by splitting the string keys into their significant parts.

const dates = ["2021-01-05T06:30:00.000Z","2021-01-06T06:30:00.000Z","2021-01-20T06:30:00.000Z","2021-02-09T06:30:00.000Z","2021-02-23T06:30:00.000Z","2021-02-16T06:30:00.000Z","2020-12-08T06:30:00.000Z","2020-12-15T06:30:00.000Z","2020-12-02T06:30:00.000Z","2020-12-09T06:30:00.000Z","2020-12-16T06:30:00.000Z"];

const grouped = dates.reduce((accumulator, date) => {
  const parsed = new Date(date);
  const year = parsed.getFullYear();
  const month = parsed.getMonth();
  const groupKey = `${month},${year}`;
  accumulator[groupKey] = accumulator[groupKey] || {dates: []};
  accumulator[groupKey].dates.push(parsed.getDay());
  return accumulator;
}, {});

const result = Object.entries(grouped).map(([key, dates]) => {
  const parts = key.split(',');
  return {
    month: parts[0],
    year: parts[1],
    dates: dates
  };
});

console.log(result);

One simple solution is to use an object to group by month and year like below:

const data = ["2021-01-05T06:30:00.000Z","2021-01-06T06:30:00.000Z",
    "2021-01-20T06:30:00.000Z","2021-02-09T06:30:00.000Z",
    "2021-02-23T06:30:00.000Z","2021-02-16T06:30:00.000Z",
    "2020-12-08T06:30:00.000Z","2020-12-15T06:30:00.000Z",
    "2020-12-02T06:30:00.000Z","2020-12-09T06:30:00.000Z",
    "2020-12-16T06:30:00.000Z"];

function groupDates(dates) {
    const groupedDates = {};
    dates.forEach(d => {
        const dt = new Date(d);
        const date = dt.getDate();
        const year = dt.getFullYear();
        const month = dt.getMonth() + 1;
        
        const key = `${year}-${month}`;
        if (key in groupedDates) {
            groupedDates[key].dates = [...groupedDates[key].dates, date];
        } else {
            groupedDates[key] = {
                year,
                month,
                dates: [date],
            };
        }

    });

    return Object.values(groupedDates);
}

console.log(groupDates(data));

Here is a pure javascript solution without using any library. It is based on a simple O(n^2) runtime. But if you like to use some libraries for like binary search you can reduce it to O(nlogn).

The trick is to brick this task into smaller task as I did with functions getMonthYear (to convert string to object), pare and addDate:

data = ["2021-01-05T06:30:00.000Z","2021-01-06T06:30:00.000Z","2021-01-20T06:30:00.000Z","2021-02-09T06:30:00.000Z","2021-02-23T06:30:00.000Z","2021-02-16T06:30:00.000Z","2020-12-08T06:30:00.000Z","2020-12-15T06:30:00.000Z","2020-12-02T06:30:00.000Z","2020-12-09T06:30:00.000Z","2020-12-16T06:30:00.000Z"];

function categorize(data) {

    // 2021-01-05T06:30:00.000Z => {month:"01", year:"2021", date:"05"}
  function getMonthYear(str) {
    var datePart = str.toString().trim().split("T")[0];
    var datePartArr = datePart.split("-");
    return {month:datePartArr[1], year:datePartArr[0], date:datePartArr[2]};
  }
  // testing
  //var ans = getMonthYear("2021-01-06T06:30:00.000Z");
  //console.log(ans);
  
  // paring two items to see if they have the same year and month
  function pare(item1, item2) {
    return (item1.month == item2.month) && (item1.year == item2.year);
  }
  // testing
  //var ans = pare({month:"04", year:"2021"}, {month:"03", year:"2021"});
  //console.log(ans);
  
  // adding a date to the list of dates
  function addDate(dateList, dateNumber) {
 
    for(var i in dateList) {
        if (dateList[i] == dateNumber) return;
    }

        dateList.push(dateNumber);
    
  }
  // testing 
  /*var ans = [2,4];
  addDate(ans, 4);
  console.log(ans);*/
  
  // Now lets build the answer by looping over
  // --------------------------------------------
  var list = []; // the final answer list
  
  data.forEach(function(str){
    var item = getMonthYear(str);
    var itemMatched = false;
    // now lopping over the list to see if it has any match
    
    for(var i in list) {
        if (pare(item, list[i])) {   // matched found
        itemMatched = true;
        addDate(list[i].date, item.date);
        break;
      }
    }
    
    // item had no match, add it as a new item to list
    if (!itemMatched) { 
        list.push({
        month: item.month,
        year: item.year,
        date: [item.date]
      });
    }    
  });
  
  return list;
  
}

var ans = categorize(data); 
console.log(ans);

Here is link to jsfiddle

发布评论

评论列表(0)

  1. 暂无评论