How can you eliminate the first elements of two or more arrays of objects until all of their first elements match based on a specific field?

My Typescript code includes a Map object called `stat_map` defined as

const stat_map: Map<string, IMonthlyStat[]> = new Map();

The interface IMonthlyStat is structured as shown below (Note that there are more fields in reality)

export interface IMonthlyStat {
  month: string;
  value: number;
}

The issue arises when the values within the Map, specifically the IMonthlyStat arrays, contain different month values due to data added at various times.

The format of the month field is '2021-02-01T00:00:00.000 UTC'.

I am looking for the most efficient way to standardize all IMonthlyStat arrays by removing initial elements so they all start with the same month string.

For example, if we have two IMonthlyStat arrays like

[
    {month: '2021-02-01T00:00:00.000 UTC', value: 6}, 
    {month: '2021-03-01T00:00:00.000 UTC', value: 8}, 
    {month: '2021-04-01T00:00:00.000 UTC', value: 10}
]

and

[
    {month: '2021-03-01T00:00:00.000 UTC', value: 7}, 
    {month: '2021-04-01T00:00:00.000 UTC', value: 9}
]

How can I achieve results like this:

[
    {month: '2021-03-01T00:00:00.000 UTC', value: 8}, 
    {month: '2021-04-01T00:00:00.000 UTC', value: 10}
]

and

[
     {month: '2021-03-01T00:00:00.000 UTC', value: 7}, 
     {month: '2021-04-01T00:00:00.000 UTC', value: 9}
]

Answer №1

In case you're interested, I have a function below that adjusts an array of arrays so that all arrays begin with the same element, assuming there is at least one common element among them. The comparison of elements is based on a specified key function:

key(A) == key(B) -> A equals B

function alignBy(arrays, keyFunction) {
    for (let item of arrays[0]) {
        let indexes = arrays.map(array => 
            array.findIndex(element => keyFunction(item) === keyFunction(element)))
        if (indexes.every(i => i >= 0))
            return arrays.map((array, index) => array.slice(indexes[index]))
    }
}

//

arrayA = [
    {month: '1', value: 6},
    {month: '2', value: 8},
    {month: '3', value: 10},
    {month: '5', value: 9},
]

arrayB = [
    {month: '2', value: 7},
    {month: '3', value: 9},
    {month: '4', value: 9},
    {month: '6', value: 9},
]

arrayC = [
    {month: '3', value: 7},
    {month: '3', value: 9},
    {month: '4', value: 9},
    {month: '5', value: 9},
]


result = alignBy([arrayA, arrayB, arrayC], x => x.month)
for (item of result) {console.log(...item); console.log('----')}

Answer №2

const MonthlyData1= [
    {month: '2021-02-01T00:00:00.000 UTC', value: 6}, 
    {month: '2021-03-01T00:00:00.000 UTC', value: 8}, 
    {month: '2021-04-01T00:00:00.000 UTC', value: 10}
]
 
const MonthlyData2= [
    {month: '2021-03-01T00:00:00.000 UTC', value: 7}, 
    {month: '2021-04-01T00:00:00.000 UTC', value: 9}
]

function compareAndRemoveDates(data1, data2){

if (data1 === data2){
    return {
        finalData1: data1,
        finalData2: data2
    }
}
 
const initialDateArray1 = data1[0].month.split('T')[0].split('-')
const initialDateArray2 = data2[0].month.split('T')[0].split('-')

const utcDate1 = new Date(initialDateArray1[0], initialDateArray1[1], initialDateArray1[2]);
const utcDate2 = new Date(initialDateArray2[0], initialDateArray2[1], initialDateArray2[2]);

const dateDiff = utcDate1 < utcDate2 // If true we need to remove Dates in array1 else we need to remove Dates in array2

if(dateDiff){
    return removeDates(data1, data2)
} else {
    return removeDates(data2, data1)
}
}


function removeDates(mutableArr, inmutableArr){
    const initialMonthInmutableArr = inmutableArr[0].month

    while(mutableArr[0].month !== initialMonthInmutableArr){
        mutableArr.shift()
    }

    return {
        finalData1: mutableArr,
        finalData2: inmutableArr
    }    
}

const { finalData1, finalData2 } = compareAndRemoveDates(MonthlyData1, MonthlyData2)

console.log(finalData1)

console.log(finalData2)

/*
[
  { month: '2021-03-01T00:00:00.000 UTC', value: 8 },
  { month: '2021-04-01T00:00:00.000 UTC', value: 10 }
]
[
  { month: '2021-03-01T00:00:00.000 UTC', value: 7 },
  { month: '2021-04-01T00:00:00.000 UTC', value: 9 }
]
*/

Answer №3

Method 1 using array.filter() and array.some()

If I understand correctly, you want to find the common elements between two arrays based on dates.

You can achieve this by using array.filter() and array.some().

You can combine these functions to find elements in array1 where the .month value also exists in array2. For your case, you can repeat this process for both arrays.

The main difference from your original request is that it searches the entire array instead of just looking for the first match, so processing time may be impacted by the array size.

let intersection = array1.filter(x => array2.some(y=> x.month === y.month));

Try running this snippet for a simple demo:

let array1 = [
    {month: '2021-02-01T00:00:00.000 UTC', value: 6},
    {month: '2021-03-01T00:00:00.000 UTC', value: 8},
    {month: '2021-04-01T00:00:00.000 UTC', value: 10}
];

let array2 = [
    {month: '2021-03-01T00:00:00.000 UTC', value: 7},
    {month: '2021-04-01T00:00:00.000 UTC', value: 9}
];

let intersection = array1.filter(x => array2.some(y=> x.month === y.month));
let intersection2 = array2.filter(x => array1.some(y=> x.month === y.month));

console.log(intersection);
console.log(intersection2);

Method 2 with findIndex()

If your arrays are always sorted by month and you're only interested in finding the first matching element, you can follow these steps:

  1. Compare the first items of both arrays to determine the latest month
  2. Use findIndex() to locate the index of that month in each array
  3. Split the arrays based on those indices

Here's a straightforward implementation with slightly more code than the first method but should be more efficient as it only checks the initial item in each array and performs a splice operation:

let array1 = [
    {month: '2021-02-01T00:00:00.000 UTC', value: 6},
    {month: '2021-03-01T00:00:00.000 UTC', value: 8},
    {month: '2021-04-01T00:00:00.000 UTC', value: 10}
];

let array2 = [
    {month: '2021-03-01T00:00:00.000 UTC', value: 7},
    {month: '2021-04-01T00:00:00.000 UTC', value: 9}
];

processedArray1 = [];
processedArray2 = [];

// Find the latest initial month from both arrays
const latestFirstMonth = array1[0].month >= array2[0].month ? array1[0].month : array2[0].month;

// Find the indices of the latest month in each array (since it will be 0 for the array with the latest month initially)
const array1Index = array1.findIndex(element => element.month >= latestFirstMonth);
const array2Index = array2.findIndex(element => element.month >= latestFirstMonth);

// Split the arrays based on these indices
processedArray1 = array1.splice(array1Index);
processedArray2 = array2.splice(array2Index);

console.log(processedArray1);
console.log(processedArray2);

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

Utilize an AJAX call to fetch an array and incorporate it within your JavaScript code

Currently, I am in the process of building a live update chart feature. To access the necessary data, I created a separate file which contains the required information. Through AJAX, I sent a request from my main page to retrieve an Array and incorporate i ...

Listening to changes in a URL using JQuery

Is there a way to detect when the browser URL has been modified? I am facing the following situation: On my webpage, I have an iframe that changes its content and updates the browser's URL through JavaScript when a user interacts with it. However, no ...

In order to properly execute the JavaScript code, it is essential to create a highly customized HTML layout from the ER

I am currently utilizing this resource to create a gallery of images on my Rails page. Here is the HTML code required to display the images: <a href="assets/gallery/ave.jpg" title="Ave" data-gallery> <img src="assets/gallery/ave_tb.jpg" alt="Av ...

Issue with Responsive Font Size functionality in Tailwind and ReactJS not functioning as expected

I'm really struggling with this issue. I grasp the concept of mobile-first design and have successfully made my website's layout responsive. However, I'm having trouble getting the font size to change when applying breakpoints as the screen ...

Invoking a controller from another controller in the Express framework using Typescript

Currently, I am trying to call a controller from another controller in my code. While attempting to pass parameters using {params: {task_id: String(task_id), result}}, TypeScript is flagging an error indicating that res does not have all the required attri ...

What seems to be the problem at hand, and where exactly is the issue located?

import React from 'react'; const card = ({name, email, id}) => { return( <div className='tc bg-light-green dib br3 ma2 grow bw2 shadow-5'> <img alt="robots" src = {'https://uniqueimage. ...

Struggles with updating app.component.ts in both @angular/router and nativescript-angular/router versions

I have been attempting to update my NativeScript application, and I am facing challenges with the new routing system introduced in the latest Angular upgrade. In my package.json file, my dependency was: "@angular/router": "3.0.0-beta.2" After the upg ...

When the button is clicked, the JavaScript function is not being executed

I'm having a strange issue with my second button not working as expected. Despite appearing to be straightforward, the "Reset" button does not seem to be triggering the clear() function. Within the HTML code, I have two buttons set up to interact wit ...

Having trouble retrieving an object from an event handler in ReactJS

const question = { quest : "What is my age?", answers : [16,15,21,30], correct : 21, } validateAnswer(){ let usersResponse = document.getElementById('ans-1').textContent; let response = this.question.correct; if(usersResp ...

Submit a HTML form to a Telegram recipient

I am looking to send HTML form data, which includes input values and select options, to a telegram user. After some research, I discovered that I need to create a Telegram bot. I successfully created one using @botFather by following these steps: /newbot ...

I can view the data retrieved in the console, but I am having difficulty displaying it on the screen

I have successfully retrieved data from the API, as indicated by the output in my console. However, I am facing issues in displaying this data on the webpage due to a potential error in my code structure. Despite this, I can confirm that the fetched data ...

Troubleshooting a mysterious anomaly with a jQuery UI button

Would like to achieve something similar to this: http://jqueryui.com/demos/button/#icons When trying to replicate it, http://jsfiddle.net/p5PzU/1/ Why is the height so small? I expected a square shape but am getting a rectangle instead. What could be c ...

Exploring disparities between the Client SDK and Admin SDK in conducting firestore queries

I am encountering difficulties with my query while running it in Firebase Functions. It functions perfectly on the client side, but fails to work in Functions. I am curious if there is a way to modify it to function with Admin SDK as well. Am I making any ...

Error: Webpack encountering reference errors when handling multiple entry points

Here is my setup in webpack.config.js: entry: { a:'./src/a.js', b:'./src/b.js' }, output: { path: path.join(__dirname, 'dist'), filename: '[name].bundle.js' } The content of a.js includes: const ...

Accessing a Child Component Function in Material UI

Utilizing the Material UI framework, I am constructing an application with React. Included in this application is a Dialog feature that permits users to modify various information about an object (referencing the code below). The dialog consists of two but ...

The $mdSticky feature in AngularJS Material seems to be malfunctioning

It's been a challenge for me to get the md-toolbar to stay in the top position. I decided to create a custom directive using the $mdSticky service in AngularJS. var app=angular.module('app',['ngMaterial']); app.controller(&apos ...

Updating the CSS style of an inner DIV using JavaScript

Can you provide guidance on how to modify the background color using JavaScript for the different styles listed below? i) Internal Style sheet and/or ii) External Style sheet I am currently working with the card deck slide show available at https://githu ...

Is it possible to efficiently share sessionStorage among multiple tabs in Angular 2 and access it right away?

My Current Knowledge: I have discovered a way to share sessionStorage between browser tabs by using the solution provided here: browser sessionStorage. share between tabs? Tools I Am Using: Angular 2 (v2.4.4) with TypeScript on Angular CLI base The ...

Endless Scroll Feature in Javascript

A brief tale: I am in search of a way to extract data from a website that features infinite scroll without actually implementing the infinite scroll feature myself. My plan is to create a script that will auto-scroll the page from the browser console, wai ...

Can we rely on the render method to display the updated state immediately after invoking setState within

Is it guaranteed that the state will exist in the render method if I call setState within componentWillMount without using a callback? According to Facebook, "componentWillMount is called before render(), therefore calling setState() synchronously in this ...