Group items in Typescript with lodash

21,112

Solution 1

You can make use of the _.groupBy() method and add a callback that returns the value you need to group it with, which is the year, month, day part of the date. You can then set the values needed by using _.map().

The example below uses ES6:

var meetings =
[
   {date:"2001-01-01 13:00", place:"park"},
   {date:"2001-01-01 14:00", place:"school"},
   {date:"2001-01-02 11:00", place:"house"}
];

var result = _(meetings)
  .groupBy(meeting => meeting.date.split(' ').shift())
  .map((meetings, day) => ({ day, meetings }))
  .value();

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/4.11.2/lodash.min.js"></script>

Here is the ES5 version:

var meetings =
[
   {date:"2001-01-01 13:00", place:"park"},
   {date:"2001-01-01 14:00", place:"school"},
   {date:"2001-01-02 11:00", place:"house"}
];

var result = _(meetings)
  .groupBy(function(meeting) { return meeting.date.split(' ').shift(); })
  .map(function(meetings, day) { return { day: day, meetings: meetings }; })
  .value();

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/4.11.2/lodash.min.js"></script>

Solution 2

If you have the typings for lodash (for newer versions of typescript do npm i --save-dev @types/lodash), methods like _.groupBy or _.keyBy accept a generics type.

Eg: _.groupBy<TypeEachGroupCarries>(expression) will return an array of arrays that contain items of the type TypeEachGroupCarries.

Solution 3

Why use a library when you already have all the tools ? :)

const dateMap  = meetings
    .reduce(
    (m, v) => {
        const day = v.date.substring(0,10)
        const entry = m[day]
        if (typeof entry === 'undefined') {
            m[day] = [v] 
        }
        else {
            entry.push(v)
        }
        return m
    },
    {}    
)

const groupedMeetings = Object.keys(dateMap).map(d => {
    return {
        day: d,
        meetings: dateMap[d]
    }
})    

See it running in the Typescript playground

Share:
21,112
jlp
Author by

jlp

Updated on June 01, 2020

Comments

  • jlp
    jlp almost 4 years

    I need to group a collection of objects by date:

    var meetings =
    [
       {date:"2001-01-01 13:00", place:"park"},
       {date:"2001-01-01 14:00", place:"school"},
       {date:"2001-01-02 11:00", place:"house"}
    ];
    

    so it becomes:

    var groupedMeetings = 
    [
       {
          day:"2001-01-01", 
          meetings: 
          [
             {date:"2001-01-01 13:00", place:"park"},
             {date:"2001-01-01 14:00", place:"school"}
          ]
       },
       {
          day:"2001-01-02", 
          meetings: 
          [
             {date:"2001-01-02 11:00", place:"house"}
          ]
       }
    ]
    

    I was able to group them with _.groupBy and _.map

    var g = _.groupBy(meetings, function(i){return getDatePart(i.date);});
    var groupedMeetings  = _.map(g, function(items,key){return {day:key, meetings:items};});
    

    But I have problems with doing the same in Typescript with https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/lodash/lodash.d.ts

    First, I declared my classes:

    class Meeting
        {
           date: Date,
           place: Meeting[]
        }
    class GroupedMeeting
        {
          constructor(private day: Date, private meetings: Meeting[]) {}
        }
    

    Now I dont know which overload of groupBy to use? And how to map it to list of grouped items?

    var grouped: _.Dictionary<Meeting[]> = _.groupBy(meetings, (i: Meeting) => { return this.getDatePart(i.date); });
    
    var groupedMeetings : GroupedMeeting[] = _.map(grouped, (items: Meeting[], key: Date) => { return new GroupedMeeting (key, items); });
    
  • jlp
    jlp about 8 years
    I got it working in JS, my issue is to write it in Typescript