What is the best way to organize text within messages?

Hey there! I have a messaging app with 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 am looking to merge message text into one message if they are sent within 60 seconds of each other.

[{"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":[]}]

This is the code I've tried so far

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

How can I improve on this? I'm open to using lodash

Thanks in advance!

Answer №1

In order to group messages based on the time difference between them, you can utilize the reduce function. If the time gap between the previous message's created_at and the current message's created_at is less than 1 minute (or 60,000ms), then add the message to the existing item's grouped_text array in the accumulator. Otherwise, create a new message within the accumulator with a grouped_text property.

To extract the message content and other properties separately from each message, you can employ destructuring assignment.

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((result, { text, ...otherProps }, index, array) => {
  const previousMsg = array[index - 1];

  if (previousMsg && groupDates(otherProps.created_at, previousMsg.created_at))
    result[result.length - 1].grouped_text.push(text)
  else
    result.push({ ...otherProps, grouped_text: [text] })

  return result;
}, [])

console.log(grouped)

Note: This logic assumes that the messages are already sorted based on the created_at timestamp.

Answer №2

The lodash's groupBy-function may not be the best fit for this scenario. Instead of putting all message-objects that match the key into an array, it would be more efficient to utilize the reduce-function.

If we assume that the list of messages (referenced in your query) is sorted by date:

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 result = messages.reduce((result, message) => {
    const lastMessage = result[result.length - 1];
    if (!lastMessage || new Date(message.created_at) - new Date(lastMessage.created_at) >= 60000) {
        message.grouped_text = [message.text]
        delete message.text;
        result.push(message);
    } else {
        lastMessage.grouped_text.push(message.text);
    }
    return result;
}, []);

console.log(result);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

There is an error in the TypeScript code where it is not possible to assign a string or

I'm struggling to resolve a typescript error. Upon checking the console log, I noticed that the regions returned by Set are an array of strings, which aligns perfectly with the region type in my state. Why isn't this setup working as expected? S ...

Injecting services differently in specific scenarios in AngularJS

I have a unique angular service called $superService that I utilize across many of my directives and controllers. However, there is one specific directive where I want to implement the following behavior: If another directive utilizes $superService in its ...

Discovering if an array includes a particular value in JavaScript/jQuery

Is there a way to check if the list with the class .sidebar contains an item with data-id="1"? <ul class="sidebar"> <li data-id="1">Option 1</li> <li data-id="2"> Option 2</li> <li data-id="3"> Option 3</li&g ...

What are some ways to customize the appearance of VueJS components?

I am new to Vue, so I apologize if this question seems silly or if I have overlooked something. I believed that you could target a custom element like this: my-element { styles go here} However, when I created an element, it appears that I can only targe ...

Exploring the JSON structure

Struggling to come up with a solution as I am limited by certain restrictions. I need to create a mobile navigation system using a JSON object provided by the proprietary server. The only allowed framework is jQuery 1.12.4, no other frameworks or updated v ...

Unable to display elements from an array in the dropdown menu generated by v-for

Having just started learning Vue.js, I am facing a challenge in rendering the following array: countries: ["US", "UK", "EU" ] I want to display this array in a select menu: <select> <option disabled value="">Your Country</option& ...

You can't send headers to the client in Express after they have already been set

I successfully registered and inserted a record in my MongoDB. However, I encountered an error when trying to log in at the line "!user && res.status(401).json("Wrong User Name");" Cannot set headers after they are sent to the client at new NodeError ...

Vue's innate lifecycle hook

I am looking for a way to automatically run a specific function as a beforeMount hook in every component of my Vue project without having to declare it individually. Essentially, I want a default behavior where if the hook is not explicitly stated in a com ...

What is the best way to append data to the end of an object using ReactJS Hooks?

Looking to set up a checkbox page in ReactJS where data is filtered by checkboxes from different categories using ReactJS hooks. Currently, I am storing the selected checkboxes as an object: { color: 'orange', shape: 'square' } ...

Tips for rearranging table columns using drag and drop in react js

I have been experimenting with various libraries to create a drag-and-drop feature for changing table columns order. Here is my current implementation: import React, { useState } from 'react'; import './list_de_tournees.css' const Table ...

Ajax UpdateProgress not functional

How can I resolve the issue where my AJAX UpdateProgress bar in ASP.NET is not running when executing a query in the correct format upon button click? Any solutions or help would be greatly appreciated. <html xmlns="http://www.w3.org/1999/xhtml"> ...

Terminate the execution of the process.exec function

Currently, I have a function in my code that is responsible for executing a specific process. Here's how it looks: static async runTest() { await process.exec(`start ${currentDir}/forward.py`); } runTest(); Here's the thing – once this Python ...

What is the best way to include rxjs in an npm library - as a dependency, peer dependency, or both?

After researching numerous posts and articles on dependencies versus peerDependencies, I am still not entirely certain what to do in my particular situation.... I have a library (which is published to a private npm repository) that utilizes rxjs; for exam ...

Encountered a problem while parsing an XML file using JavaScript from an external server

Currently, I am developing an iPhone application in HTML that needs to pull content from an XML file stored on a remote server and display it in a list. I have successfully accomplished this task when the XML file is hosted on the same server using the fo ...

Troubleshooting: JavaScript Bookmarklet Fails to Execute on Certain Websites

Recently, I created a unique bookmarklet that functions flawlessly on some websites, but unfortunately fails to work on others. Interestingly, even when it doesn't work, the script is still added to the bottom of the page; however, only a portion of t ...

When a button is clicked, the event is not triggered within a FirefoxOS application

Despite functioning perfectly on Firefox for desktop, my application encounters issues when tested on my ZTE Open C (Firefox OS 1.3). Pressing the button does not trigger any action, while onmouseup and onclick events work flawlessly. Even attempts to bin ...

Is there a way to redirect using Express JS when the destination is

Hello there, I'm encountering an issue with redirecting in express js. I have a function that should trigger when a submit button is pressed and then redirect to a different page. However, when using res.redirect('/results.ejs');, I receive ...

Using Vue.js, perform calculations on various fields within an array of objects generated by the v-for directive

I am currently learning Vue.js and I have implemented a v-for loop to iterate through an array of objects. However, I now need to calculate a specific field (precoPorKg) within this loop. In order to perform this calculation, the input item.quantidade mus ...

Is it a bad idea to incorporate JavaScript functions into AngularJS directives?

I came across this snippet of code while working with ng-repeat: <div ng-show="parameter == 'MyTESTtext'">{{parameter}}</div> Here, parameter represents a string variable in the $scope... I started exploring if it was possible to c ...

Is it possible to utilize the import feature to access and read a JSON file within a Next.js 13 API scenario?

Currently, in my Next.js 13 project, I am using the App Router feature to work with an API route that reads a file from a language folder within the resources directory. The code structure of this API is as follows: // app/api/file/[lang]/write/route.ts i ...