Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using groupBy and map to transform data using LoDash and Moment

I am inexperienced with lodash, but I believe it can help me transform data into a desired format. I have tried varying level of methods described in the documentation, but I can not wrap my head around everything. I've looked here on SO, a few blogs, and the documentation. I have tried combining groupby and map, but I was unable to resolve the issue. I was also unsure how to log the steps.

Here is what I want to do, I want to take the following array and turn it into the array after it. Can anyone point me in the right direction?

Original Data

var mockData = [
      {
        "notice_title": "Bad news",
        "notice_text": "Server is down!",
        "start_date": "2016-09-18T04:00:00Z"
      },
      {
        "notice_title": "Weekly Reminder",
        "notice_text": "Please read the assignment!",
        "start_date": "2016-09-18T04:00:00Z"
      },
      {
        "notice_title": "Sweet",
        "notice_text": "This morning, the new edition of our blog hit stands!",
        "start_date": "2016-09-19T04:00:00Z"
      },
      {
        "notice_title": "Yeah",
        "notice_text": "This is pretty cool",
        "start_date": "2016-09-19T04:00:00Z"
      }

Desired Data

var newMockData = [
    { 
        "date": "JAN 18 2016", 
        "messages": [{
            "notice_title": "Bad news",
            "notice_text": "Server is down!",
            "start_date": "2016-09-18T04:00:00Z"
          },
          {
            "notice_title": "Weekly Reminder",
            "notice_text": "Please read the assignment!",
            "start_date": "2016-09-18T04:00:00Z"
          }],
        "date": "JAN 19 2016", 
        "messages": [{
            "notice_title": "Sweet",
            "notice_text": "This morning, the new edition of our blog hit stands!",
            "start_date": "2016-09-19T04:00:00Z"
          },
          {
            "notice_title": "Yeah",
            "notice_text": "This is pretty cool",
            "start_date": "2016-09-19T04:00:00Z"
          }]

}]

Updated lodash

var result = _.chain(mockData)
      .groupBy(function(item) {
        return moment(item.start_date.substring(0,10)).format("MMM-DD-YYYY"); 
      })
      .map((value, key) => {
        return {
          date: key, 
          param: value
        }
      })
      .value();
like image 446
defaultcheckbox Avatar asked Sep 21 '16 21:09

defaultcheckbox


1 Answers

I did answer a very similar question yesterday, however, I will still provide an answer here by modifying the previous one

var mockData = [
      {
        "notice_title": "Bad news",
        "notice_text": "Server is down!",
        "start_date": "2016-09-18T04:00:00Z"
      },
      {
        "notice_title": "Weekly Reminder",
        "notice_text": "Please read the assignment!",
        "start_date": "2016-09-18T04:00:00Z"
      },
      {
        "notice_title": "Sweet",
        "notice_text": "This morning, the new edition of our blog hit stands!",
        "start_date": "2016-08-19T04:00:00Z"
      },
      {
        "notice_title": "Yeah",
        "notice_text": "This is pretty cool",
        "start_date": "2016-09-19T04:00:00Z"
      }
]

var result = _.chain(mockData)
  .groupBy(datum => moment(datum.start_date).format("MMM DD YYYY").toLocaleUpperCase() )
  .map((messages, date) => ({ date, messages })) //using ES6 shorthand to generate the objects
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.1/lodash.min.js"></script>

The key thing here is that when using _.groupBy, you can supply a function that defines how objects are collected together. In this case, this is using Moment.js in order to format the start_date of the messages into Month-day-year format:

moment(datum.start_date).format("MMM DD YYYY")` 

this will parse the date of the message and output it in <Short month> <day> <year> format. See more on formatting in the documentation. This value is then converted to upper case to transform "Sep" to "SEP"

The second thing is just generating the new structure inside the .map. Since all the information needed is already present formatted like so

{
    "Sep 18 2016": [{
        "notice_title": "Bad news",
        "notice_text": "Server is down!",
        "start_date": "2016-09-18T04:00:00Z"
    }, {
        "notice_title": "Weekly Reminder",
        "notice_text": "Please read the assignment!",
        "start_date": "2016-09-18T04:00:00Z"
    }],
    "Aug 19 2016": [{
        "notice_title": "Sweet",
        "notice_text": "This morning, the new edition of our blog hit stands!",
        "start_date": "2016-08-19T04:00:00Z"
    }],
    "Sep 19 2016": [{
        "notice_title": "Yeah",
        "notice_text": "This is pretty cool",
        "start_date": "2016-09-19T04:00:00Z"
    }]
}

It's a simple matter of getting the keys and turning them into a property and the values and being added as another property.

like image 145
VLAZ Avatar answered Oct 21 '22 14:10

VLAZ