Organize data by month and year using Underscore.js groupBy method

This is my JSON Input:

"data": [
        {
            "id":3,
            "created_by": 1,
            "created_at": "2022-01-31T07:00:01.880Z",
        },
        {
            "id":2,
            "created_by": 1,
            "created_at": "2022-01-31T07:00:01.880Z",
        },
        {
            "id":1,
            "created_by": 1,
            "created_at": "2022-01-31T07:00:01.880Z",
        }
    ]

I am trying to sort the resulting JSON output by year and month. I have successfully grouped them by year and month separately using the code below, but I'm struggling to combine both groupings into one result. The code and outputs are provided below:

    var groupedByYear = _.groupBy(flashMessage,function(item:any) {
        return item.created_at.getFullYear();
    });

    var groupedByMonth = _.groupBy(flashMessage,function(item:any) {
        return item.created_at.getMonth();
    });

Both functions are returning the results correctly as shown below:

  1.  "2021": [
                {
                    "created_by": 1,
                    "created_at": "2021-01-31T06:54:27.733Z",
                }
            ],
           "2022": [
                {
                    "created_by": 1,
                    "created_at": "2022-01-31T06:54:27.733Z",
                }
            ],
    

However, I would like the result to be structured like this:

   "2021": [
               0:[ {
                    "created_by": 1,
                    "created_at": "2021-01-31T06:54:27.733Z",
                }]
            ],
           "2022": [
               0:[ {
                    "created_by": 1,
                    "created_at": "2022-01-31T06:54:27.733Z",
                }]
               1:[ {
                    "created_by": 1,
                    "created_at": "2022-02-31T06:54:27.733Z",
                }]

            ],

Can someone help me achieve this? I am using TypeScript with Node.js and PostgreSQL as my database.

Answer №1

Achieving this task without using underscores is possible by employing a simple reduce function

const flashMessages = [
            {
             "created_by": 1,
             "created_at": "2021-01-31T06:54:27.733Z",
             },
           {
             "created_by": 2,
             "created_at": "2021-02-25T06:54:27.733Z",
             },
            {
             "created_by": 3,
             "created_at": "2021-01-31T06:54:27.733Z",
             },
          {
         "created_by": 3,
         "created_at": "2022-02-01T06:54:27.733Z",
         },
         
         ]
         
         const months = [
           'jan',
           'feb',
           'mar',
           'apr',
           'may',
           'jun',
           'jul',
           'sep',
           'oct',
           'nov',
           'dec'
         ]
         
const result = flashMessages.reduce((res, item) => {
   const date = new Date(item.created_at)
   
   const year = date.getFullYear();
   const month = months[date.getMonth()]
   
   const existingYear = res[year] || {}
   res[year] = existingYear
   const updated  = [...(existingYear[month] || []), item]
   
   res[year][month] = updated
   
   return res
}, {});

console.log(result)

Answer №2

To achieve the desired outcome in a sleek functional manner, consider incorporating _.mapObject.

var data = [{
    "id": 3,
    "created_by": 1,
    "created_at": "2022-01-31T07:00:01.880Z",
}, {
    "id": 2,
    "created_by": 1,
    "created_at": "2022-01-31T07:00:01.880Z",
}, {
    "id": 1,
    "created_by": 1,
    "created_at": "2022-01-31T07:00:01.880Z",
}];

var months = 'jan feb mar apr may jun jul aug sep oct nov dec'.split(' ');

function getDate(item) {
    return new Date(item.created_at);
}

function getMonth(item) {
    return months[getDate(item).getMonth()];
}

function getYear(item) {
    return getDate(item).getFullYear();
}

function groupByMonths(items) {
    return _.groupBy(items, getMonth);
}

var byYear = _.groupBy(data, getYear);
var result = _.mapObject(byYear, groupByMonths);

console.log(result);
<script src="https://underscorejs.org/underscore-umd-min.js"></script>

To save time and effort, utilize _.partial to avoid writing the groupByMonths function separately. This simplifies the last line to:

var result = _.mapObject(byYear, _.partial(_.groupBy, _, getMonth));

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

Issue with loading CSS in Angular 8 upon refreshing the page after building in production

Here is the structure of my index.html: <!doctype html> <html lang="hu"> <head> <meta charset="utf-8"> <title>WebsiteName</title> <base href="/"> <meta name="viewport& ...

Tips for dynamically expanding a generic interface depending on the keys of its parent object

Consider the following definitions: interface A { id?: string; name?: string; } interface BaseLabel<B extends Parent, Parent extends A> { keyStr?: keyof B & string; } interface RequiredLabel<B extends Parent, Parent extends A> ...

Differences between FirebaseFirestore.Timestamp and firebase.firestore.Timestamp in a React Native client and Admin Node server context

Currently facing an issue that seems straightforward but is proving difficult to resolve. Despite thorough documentation review and a lack of similar inquiries, I am encountering difficulties. My project involves building an app using React Native, where ...

Tips for updating TypeScript aliases during compilation

To define a typescript alias in tsconfig.json, you can use the following syntax: "paths": { "@net/*":["net/*"], "@auth/*":["auth/*"], }, After defining the alias, you can then use it in you ...

When utilizing TS Union Types from an Array, the resulting type will consistently be a

After reading this response, I decided to create some union types from a string[] in order to return a list of valid type values. However, instead of that, the type ends up accepting any string value. const arrayDays = Array.from(Array(32).keys(), (num) =& ...

Creating Multiple Routes in a Single TypeScript and AngularJS Route File

I have built a module with TypeScript and AngularJS that includes multiple pages. I would like to use one TypeScript controller per page. How can I define multiple controllers in my routes? Currently, I have only defined one, but what if I have 6 or 7 co ...

Choose all the checkboxes that use Knockout JS

Struggling with implementing a "select all" checkbox feature as a Junior developer on a complex project utilizing knockout.Js and Typescript. I can't seem to figure out how to select all existing checkboxes. Here is the HTML: <td> <inp ...

Steps for setting up single sign on in an Angular 2 application

Currently, I am working on a web application that has been developed using angular2. One of the requirements for this application is to incorporate a single sign-on feature, where users do not have to manually input their login credentials. Instead, the ap ...

How can we optimize ternary statements within ternary statements in Type Script and React Native for best practices?

Can you help me optimize this code snippet that uses nested ternary operators for better readability and correctness? <TouchableOpacity style={ darkMode ? filterState === 'A' ? styles.activeButtonDark : styles.buttonDa ...

What is the best way to implement callbacks with $http in Typescript?

When making my $http call, I am looking for the most adaptable way to handle all the parameters returned in the .success and .error functions. Here is an example of what my $http call looks like: this.$http({ url: "/api/x", method: "GET" }) .success((? ...

Utilizing D3 to fetch geographic data in the form of a TopoJSON file for U.S. counties

After retrieving a set of coordinates, the goal is to use D3 to find the corresponding county from a U.S. TopoJSON file. Here is an example code snippet: navigator.geolocation.getCurrentPosition(function(position) { let coordinates: [number, number] = [p ...

Error in TypeScript: The property "component" is not found on the React MUI MenuItem

I am currently working with the react mui MenuItem component and I am trying to turn a menu item into a link. Here is how I have attempted to achieve this: <MenuItem component={<Link href={`/backend/api/exam/${row.id}/result`} />} className={c ...

Searching for a streamlined approach to retrieve a segment of a string

I'm currently working with JavaScript and TypeScript. Within my code, I encountered a scenario where I have a string that might contain certain tags indicating importance or urgency. Here are a couple of examples: A: "Remind me to go to the store to ...

Issues with Angular2 causing function to not run as expected

After clicking a button to trigger createPlaylist(), the function fails to execute asd(). I attempted combining everything into one function, but still encountered the same issue. The console.log(resp) statement never logs anything. What could be causing ...

Array that accepts the type of the first element as its generic parameter

There was a type challenge The task was to create a generic function called First that takes an array T and returns the type of its first element. type arr1 = ["a", "b", "c"]; type arr2 = [3, 2, 1]; type head1 = First<arr1>; // expected: 'a& ...

Grab the inner html content of a specific element and release it into a different element by holding down the mouse button

I am working with a grid that has a start node. My goal is to make this node a draggable object without moving the HTML element itself, as it contains important information about that particular node (such as position and state). Instead, I only want to mo ...

Verifying data types in TypeScript

When working with TypeScript in the browser, I often find myself writing code like this: const button = document.getElementById(id); if (!(button instanceof HTMLButtonElement)) { throw new Error("TODO -- insert better error message here"); } bu ...

Waiting patiently for the arrival of information, the dynamic duo of Angular and Firebase stand poised and

Here is the given code snippet: signIn(email, password) { let result = true; firebase.auth().signInWithEmailAndPassword(email, password).catch(error => result = false); waits(100); return result; } I have a ...

Dealing with Errors in Node.js Using Typescript and Express

As I embark on my journey with Node and Typescript, a question has cropped up in my mind. There are two key files in my project: server.ts import express = require('express'); import IConfiguration from "../config/config"; export default clas ...

Angular 7 is unable to connect to <property> as it is not recognized as a valid property of <component> in the imported module

I have been facing an issue with my module setup where ModuleA is importing ModuleB to use a component declared within it. The specific problem arises when ModuleAComponentC attempts to utilize ModuleBComponentA. While logic dictates that ModuleA should im ...