Getting the data from the final day of every month in a Typescript time-series object array

I am dealing with timeseries data retrieved from an API that consists of random dates like the following:

[
  {
    "id": 1,
    "score": 23,
    "date": "2023-08-30"
  },
  {
    "id": 2,
    "score": 62,
    "date": "2023-08-22"
  },
  {
    "id": 3,
    "score": 82,
    "date": "2023-07-27"
  }
          .
          .
          .
]

My goal is to efficiently extract the data corresponding to the last day of each month. The desired output should look something like this:

[
  {
    "id": 1,
    "score": 23,
    "date": "2023-08-30"
  },
  {
    "id": 3,
    "score": 82,
    "date": "2023-07-27"
  }
          .
          .
          .
]

To achieve this, I am currently experimenting with a function like the one below:

const getMonthlyData = (allData: Timeseries[]): Timeseries[] => {

//Iterate over each entry to identify the maximum date per month and include it in the return array

}

Restructured for clarity and better readability

Answer №1

Imagine you have an array called scores containing various data.

This method involves creating a middleman object that links a specific month and year to the most recent entry, then extracting those values back into the desired array format.

It's worth noting that while theoretically the order may not remain consistent (due to JS spec on object key ordering), practically speaking in modern browsers and js runtimes like node, it usually does maintain order.

If maintaining strict order is crucial, consider sorting by date field afterward. However, this step is often unnecessary in practice.

In cases where there are multiple entries with identical dates, this approach selects the last one due to the use of the >= operator. To switch to the first one, change it to >.

You can test this solution using the provided playground.

type Timeseries = {
  id: number
  score: number
  date: string
}

let scores: Timeseries[] = [
  {
    id: 1,
    score: 23,
    date: "2023-08-30",
  },
  {
    id: 2,
    score: 62,
    date: "2023-08-22",
  },
  {
    id: 3,
    score: 82,
    date: "2023-07-27",
  },
]

const lastOfMonthScores = Object.values(
  scores.reduce<Record<string, Timeseries>>(
    (keyedTimeSeries, currentTimeSeries) => {
      const currentDate = new Date(currentTimeSeries.date)
      const currentKey = `${currentDate.getFullYear()}-${currentDate.getMonth()}`
      const existingEntry = keyedTimeSeries[currentKey]
      const existingDate = existingEntry
        ? new Date(existingEntry.date)
        : undefined
      return {
        ...keyedTimeSeries,
        [currentKey]: existingDate
          ? currentDate >= existingDate
            ? currentTimeSeries
            : existingEntry
          : currentTimeSeries,
      }
    },
    {},
  ),
)

console.log(lastOfMonthScores)

https://i.sstatic.net/Xwpev.png

Answer №2

const MONTHLY_DATE_REGEX = /(\d{4}-\d{2})-\d{2}/

const extractMonthlyData = (allData: Timeseries[]): Timeseries[] => {
  const monthMaxValues: Record<string, Timeseries> = {}
  for (const data of allData) {
    const match = data.date.match(MONTHLY_DATE_REGEX)
    if (!match) {
      throw new Error(`Invalid date format detected: ${data.date}`)
    }
    const monthYear = match[1]
    if (!monthMaxValues[monthYear] || monthMaxValues[monthYear].date < data.date) {
      monthMaxValues[monthYear] = data
    }
  }
  return Object.values(monthMaxValues)
}

This function relies on properly formatted dates, which are ensured by using a regular expression. It constructs an object that stores each year/month combination as keys and the maximum value for that year/month as the corresponding values. The advantage of using ISO format dates like this is that they can be sorted alphabetically, allowing for easy comparison of date strings.

Code Playground

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 Angular 11: Unable to bind to 'ngForOf' as it is not recognized as a valid property of 'tr' element

My issue lies with a particular page that is not functioning correctly, even though it uses the same service as another working page. The error seems to occur before the array is populated. Why is this happening? I appreciate any help in resolving this p ...

Ways to limit the combination of general types in Typescript?

Struggling to develop a React form component with generic types. The initialValues parameter determines the generic type for the form. Unable to figure out how to specify the type for each field in Typescript. Check out my CodeSandbox where I've at ...

How can I subscribe to nested JSON objects in Angular?

I am seeking advice on working with a nested JSON object. Within our server, there is an object located at "/dev/api/sportstypes/2" structured like this; { "NBA": { "link": "https://www.nba.com/", "ticketPrice": 50 }, "UEFA": { ...

The interconnectivity between ngAfterViewInit in Angular's LifeCycle and observables

enable.service.ts @Injectable({ providedIn: 'root' }) export class EnableService { isEnabled$ = from(this.client.init()).pipe( switchMap(() => this.client.getEnabled()), map(([enabled, isAdmin]) => ({enabled: true, isAdmin: fals ...

Ongoing state configuration in a React hook

My custom hook: export function useToken2() { const { data: session, status } = useSession(); const [token, setToken] = useState<string | null>(null); useEffect(() => { if (status === 'authenticated' && session?.accessToken) { ...

Decorating AngularJS' ExceptionHandler with TypeScript is not feasible because a function is not identified as such

Scenario: In the project I am currently involved in, there has been a transition from utilizing AngularJS (1.6.2) with JavaScript to TypeScript 2.1.5. We had implemented a decorator on the $exceptionHandler service which would trigger a call to a common ...

Utilize a fresh function in Angular to retrieve and store data from a URL into a variable

Currently, I am attempting to utilize Angular in order to retrieve data from a link upon clicking a button. As a newcomer to Angular with only 2 days experience, my knowledge is quite limited. What I aim to achieve is triggering the loading of JSON data w ...

Ways to simulate a variable imported in the module being tested without it being a function parameter can be achieved by using describe.each and changing the mock value for each test

I have a requirement to test a function within my TypeScript module. module-to-test.ts import { config } from './app-config'; export const isSomethingWhatINeedSelector = createSelector( firstDependencySelector, secondDependencySelector ...

Implementing validation logic on button click using TypeScript

I'm struggling to get my validation to work for empty fields using the method below. Can anyone provide some guidance or suggestions? Thanks. Here is my template: <form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" class="nobottommargin ad ...

How can I verify the validity of a regular expression in Typescript without encountering a syntax error?

I am facing an issue with my code where I load a set of regular expressions from an external source. My goal is to determine if a given string is a valid regex without causing the application to crash due to a syntax error. Despite trying to use try/catch ...

Utilize Knex to retrieve data from the req.query

express and knex have been giving me some trouble; I am struggling to get this endpoint working using req.querys (response from express), even though it worked fine when I used req.params. Express: app.get(`/actor`, async (req: Request, res: Response) =&g ...

The Angular TypeScript service encounters an undefined issue

Here is an example of my Angular TypeScript Interceptor: export module httpMock_interceptor { export class Interceptor { static $inject: string[] = ['$q']; constructor(public $q: ng.IQService) {} public request(config: any) ...

I am encountering issues with running my tests using react-testing-library alongside TypeScript

Currently facing issues with react-testing-library in my TypeScript-based React project. Despite researching and following various tutorials, I am unable to resolve the problem. I have experimented with changing configurations in babel.config.js, tsconfig ...

Moving from Http to HttpClient in Angular4Changeover your Angular4

I recently migrated my Angular app to use the new HttpClient, but I'm encountering some challenges in achieving the same results as before with Http. Can anyone help me out? Here's what I was doing with Http: getAll() { return this.http.get ...

The interaction between Nextjs router and useEffect resulting in unintended re-rendering

I'm currently facing a challenge with Next.js's next/navigation router. In my component, I have a series of useEffects implemented. Strangely, when I call router.replace, one of the effects runs twice or even infinitely in some cases. As a result ...

center a horizontal line using StyledSheets in your project

After drawing a horizontal line, I noticed that it is positioned towards the left side of the screen. I am hesitant to increase its width. Are there any other methods to move it to the center? I attempted wrapping it with another view and using alignConten ...

Navigating session discrepancies: Combining various social media platforms using Next.js and NextAuth

Recently, I ran into a problem where, upon logging in with Google, I found myself needing access tokens for Twitter and LinkedIn to send out API requests. The issue came about when NextAuth modified my session data to be from either Twitter or LinkedIn ins ...

Can anyone provide a solution for fixing TypeScript/React error code TS7053?

I encountered an error message with code TS7053 which states: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; isLandlocked: boolean; }'. No index signa ...

Typegoose's representation of modifying data

Recently, I delved into the world of NestJS and kickstarted a sample project. To integrate MongoDB seamlessly, I opted for Typegoose. A useful online tutorial () caught my eye, illustrating how to employ abstractions with base typegoose models. Hence, my ...

Converting language into class components using ngx-translate in Angular

Seeking to convert the information from a table into my typescript class. The data in the table is sourced from a JSON file within the /assets directory. Is there a method to accomplish this task? How can I categorize translation within a typescript class ...