11

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();
defaultcheckbox
  • 739
  • 2
  • 5
  • 16
  • OK, what _is_ that structure? [I answered a very similar question](http://stackoverflow.com/questions/39604832/merge-array-of-complex-objects-by-using-lodash/39605199#39605199) yesterday and it seemed to be getting the same format of data and expecting it to be formatted the similarly afterwards. – VLAZ Sep 21 '16 at 21:15
  • Thanks. I am not sure I can answer "what is that structure." We get notices as list like mockData, but on the front end we want to group notices by data and display the notices under each day. I'd rather manipulate the data in the controller, instead of doing workarounds in the view. – defaultcheckbox Sep 21 '16 at 21:22
  • Are the `date` properties in the result _required_ to be the ones you specified or is that a mistake? I assume `JAN 19 2016` should actually be based on the date of the messages, and that is September. – VLAZ Sep 21 '16 at 21:33
  • The date should be JAN 19 2016. I looked at you other answer and it solved the issue for me, but I had a question about param: _.map(value, o => _.omit(o, 'index')). Is the best practice to edit my question with the update, or start a new question? – defaultcheckbox Sep 21 '16 at 21:40
  • So did that answer resolve your problem? I'm in the process of writng a new one using Moment. Also, there is no `omit/pick` needed here. – VLAZ Sep 21 '16 at 21:41
  • yes it resolved my problem. i would like to you to get credit. I'll show what I came up with in the edits. – defaultcheckbox Sep 21 '16 at 21:43
  • wait, when you say that the date has to be JAN - how do you determine the month? Because the messages are dated from September – VLAZ Sep 21 '16 at 21:47
  • I see what you meant.. yes your right it should be Sept – defaultcheckbox Sep 21 '16 at 21:49
  • Ah, I see. In that case, I just transformed the dates into uppercase in my answer. I hope that helps. – VLAZ Sep 21 '16 at 21:50

1 Answers1

18

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.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • 2
    Mostly unrelated bit of information but `data` is plural, and since it is a Latin word, the singular case is `datum`. – VLAZ Sep 21 '16 at 21:52