Search code examples
javascriptarraysvue.jslodashjavascript-objects

How to group text in messages?


Good day! I have a chat and сhat has arrays of messages.

[{"id":4,
"user_id":1,
"messageable_id":3,
"messageable_type":"conversation",
"text":"Text 1",
"action":null,
"target_id":null,
"created_at":"2019-06-17 15:47:55",
"updated_at":"2019-06-17 15:47:55",
"replies":[],
"files":[]},

{"id":5,
"user_id":1,
"messageable_id":3,
"messageable_type":"conversation",
"text":"Text 2",
"action":null,
"target_id":null,
"created_at":"2019-06-17 15:48:00",
"updated_at":"2019-06-17 15:48:00",
"replies":[],
"files":[]}]

I want to combine message text in one message, if the time difference is less than 60 seconds

[{"id":4,
"user_id":1,
"messageable_id":3,
"messageable_type":"conversation",
"grouped_text":["Text 1","Text 2"], //GROUP 
"action":null,
"target_id":null,
"created_at":"2019-06-17 15:47:55",
"updated_at":"2019-06-17 15:47:55",
"replies":[],
"files":[]}]

I try this code

let messages = this.$store.getters['conversation/messages'](this.conversation);
let grouped = _.groupBy(messages, message => {
    return this.$moment(message.created_at).startOf('minute');
});

How do i do this better? I can use lodash

Thank you in advance


Solution

  • You could use reduce. If the previous message's created_at and current message's created_at's difference is less than 1 minute (or 60,000ms), push the message to last item's grouped_text in accumulator. Else, push a new message to the accumulator with a grouped_text property

    You can destructure each message to get text and rest of the properties separately

    const messages=[{"id":4,"user_id":1,"messageable_id":3,"messageable_type":"conversation","text":"Text 1","action":null,"target_id":null,"created_at":"2019-06-17 15:47:55","updated_at":"2019-06-17 15:47:55","replies":[],"files":[]},{"id":5,"user_id":1,"messageable_id":3,"messageable_type":"conversation","text":"Text 2","action":null,"target_id":null,"created_at":"2019-06-17 15:48:00","updated_at":"2019-06-17 15:48:00","replies":[],"files":[]}]
    
    const groupDates = (date1, date2) => (new Date(date1) - new Date(date2) < 60000)
    
    const grouped = messages.reduce((r, { text, ...rest }, i, arr) => {
      const prev = arr[i - 1];
    
      if (prev && groupDates(rest.created_at, prev.created_at))
        r[r.length - 1].grouped_text.push(text)
      else
        r.push({ ...rest, grouped_text: [text] })
    
      return r;
    }, [])
    
    console.log(grouped)

    Note: This assumes that the messages are sorted according to the created_at