collection of items with varying dates

I have an array of objects, each containing a date. My goal is to create a new array of objects grouped by weeks. Here is an example code snippet:

const data = [
  {
    "id": 1,
    "status": 1,
    "createdAt": "2022-05-01T08:28:36.284Z"
  },
  {
    "id": 2,
    "status": 2,
    "createdAt": "2022-05-02T07:17:11.724Z"
  },
  {
    "id": 3,
    "status": 3,
    "createdAt": "2022-05-10T07:03:44.465Z"
  },
  {
    "id": 4,
    "status": 3,
    "createdAt": "2022-05-11T16:17:48.863Z"
  }
]

The desired result is an array that groups objects by weeks as follows:

const newData = [
  {
    "week": 1,
    "status": 1,
    "status": 2
  },
  {
    "week": 2,
    "status": 3,
    "status": 3
  }]

Is this achievable? Can a property appear multiple times in the same object? Thank you

Answer №1

To efficiently determine the week number for charting purposes, it is recommended to incorporate moment.js into your project. Here's a suitable approach:

const data = [
  {
    "id": 1,
    "status": 1,
    "createdAt": "2022-05-01T08:28:36.284Z"
  },
  {
    "id": 2,
    "status": 2,
    "createdAt": "2022-05-02T07:17:11.724Z"
  },
  {
    "id": 3,
    "status": 3,
    "createdAt": "2022-05-10T07:03:44.465Z"
  },
  {
    "id": 4,
    "status": 3,
    "createdAt": "2022-05-11T16:17:48.863Z"
  }
]
console.log(data.map(a => {
        return {
        status : a.status,
        week: moment(a.createdAt).week()
    }
    }
))
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>

The resulting array will display as follows:

[{
  status: 1,
  week: 19
}, {
  status: 2,
  week: 19
}, {
  status: 3,
  week: 20
}, {
  status: 3,
  week: 20
}]

Answer №2

When working with ECMAScript, it's important to remember that an object cannot have multiple properties with the same name. One way to handle this limitation is by using an array of objects structured like:

[{week: weekNo, statuses: [status0, status1, status2, …]}]

Since week numbers repeat every year, including the year in a format such as 2022W03 following ISO 8601 standards can help with parsing and sorting chronologically. This approach also accounts for transitioning dates across different years.

The combination of Array.prototype.reduce along with a function for calculating the week number can efficiently handle this task:

// Calculate ISO week number where week starts on Monday,
// first week contains 4 Jan or first Thursday of the year
function getWeekNumber(d) {
    let z = n => (n<10? '0' : '') + n; 
    d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
    d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
    var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
    var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
    return `${d.getUTCFullYear()}W${z(weekNo)}`;
}

function groupByWeek(data) {
  // Index pointer for week in array
  let index = {};
  let newData = data.reduce((acc, obj) => {
    let weekNo = getWeekNumber(new Date(obj.createdAt));
    if (!index[weekNo]) {
      index[weekNo] = acc.length;
      acc.push({week: weekNo, statuses: []});
    }
    acc[index[weekNo]].statuses.push(obj.status);
    return acc;
  }, []);
  // Sort by week number
  newData.sort((a, b) => a.week.localeCompare(b.week));
  return newData;
}

let data = [
  {"id": 1, "status": 1, "createdAt": "2022-05-01T08:28:36.284Z"},
  {"id": 2, "status": 2, "createdAt": "2022-05-02T07:17:11.724Z"},
  {"id": 3, "status": 3, "createdAt": "2022-05-10T07:03:44.465Z"},
  {"id": 4, "status": 3, "createdAt": "2022-05-11T16:17:48.863Z"},
  {"id": 5, "status": 1, "createdAt": "2023-01-05T08:28:36.284Z"},
];

console.log(groupByWeek(data))

Answer №3

To avoid having multiple properties with the same name in an object, it is recommended to store status values in an array.

const getWeekNumber = (date) => {
    date = formatDate(date);
    let firstDay = new Date(date.getFullYear(), 0, 1);
    let numberOfDays = Math.floor((date - firstDay) / (24*60*60*1000));
    return Math.ceil((date.getDay() + 1 + numberOfDays) / 7);
}

const formatDate = (date) => new Date(Date.parse(date));

const groupBy = (arr, key) => arr.reduce((result, item) => {
        (result[item[key]] = result[item[key]] || []).push(item);
        return result;
    }, {});

const formattedData = data.map(d => ({...d, week: getWeekNumber(d.createdAt)}));                                       // calculate week number
const groupedData = groupBy(formattedData, 'week');                                                                 // group data by week property's value
const result = Object.values(groupedData).map(arr => ({week: arr[0].week, status: arr.map(d => d.status)}));    // format result

console.log(result);

// Output
// [
//     { "week": 18, "status": [1, 2] },
//     { "week": 19, "status": [3] },
//     { "week": 20, "status": [3] }
// ]

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

Difficulty dealing with Firestore using get() followed by add()

Recently started learning Vue.js and Firestore, facing a challenge with what should be a simple task. 1) I am trying to fetch default values from an existing template document in my Firestore database. 2) The goal is to use these default values to create ...

JSONP callback function enables cross-domain communication by allowing a

After delving into the world of JSONP callback functions, I decided to familiarize myself with the concept by researching articles. To further understand JSONP, I uploaded a JSON file onto the server - json file Below is the JavaScript code I used to fet ...

Transforming astropy table columns into a numpy array

I wish to create a plot with points: points = np.random.multivariate_normal(mean=(0,0), cov=[[0.4,9],[9,10]],size=int(1e4)) print(points) [[-2.50584156 2.77190372] [ 2.68192136 -3.83203819] ..., [-1.10738221 -1.72058301] [ 3.75168017 5.6 ...

Using Google App Script to transfer specific columns of a row to a different tab based on the value in a particular column

I have a script that moves rows based on a specific value in a column, but I am looking to only transfer certain columns within those rows. This is the current script I am using: //Script to move rows from Form tab to Des tab function moveSafeRows() { v ...

Typescript - Inline check for undefined not properly functioning (Potential 'undefined' object detected.ts(2532))

I encountered an issue with TypeScript: const myFunction = ( param1: string | undefined, param2: { someProp: string } | undefined ) => { if (!param1 && !param2) { return; } // I am facing this Typescript error here: // (parame ...

JS Tips for using the .push() function with Multidimensional Arrays in JavaScript

After coming across this code example online, I decided to give it a try. The code snippet involved using the JavaScript array push method to add new elements to an inner sub-array, which was exactly what I needed to achieve! The code successfully demons ...

When triggered, the onClick event will launch multiple Material-UI dialogs simultaneously

I'm working on creating a user-friendly employee directory using Material-UI's dialog modals. However, I'm facing an issue where clicking on any employee card opens all dialog boxes instead of just the one related to that specific employee. ...

Explain and suggest the necessary parameters for a function

Is there a way to clearly describe the parameters required by my function and make them visible when I am typing my code? For instance, if we consider the ExpressJS render function below, it effectively shows what the callback expects and will return. In ...

Creating a three.js shader that continuously moves the vertices of a point cloud within a sphere

My current project involves creating a points cloud with moving points that are confined within a sphere of a specified radius, X. Initially, I was able to achieve this without using shaders, but now I am experimenting with shaders to enhance the effect. ...

Creating Angular Custom Form Validation and Custom Directives

I recently created a custom validation directive and applied it to the form element like this: <form myValidations> app.directive('myValidations', function(){ return{ //require: 'ngModel', note its commented out link: f ...

Updating React state using a form input

Seeking assistance on retrieving form values and storing them in state. Despite following various guides (mostly in class style react), I keep encountering the same error: "Nothing was returned from render. This usually means a return statement is m ...

Delete any classes that start with a specific prefix

Within my code, there is a div that holds an id="a". Attached to this div are multiple classes from different groups, each with a unique prefix. I am uncertain about which specific class from the group is applied to the div in JavaScript. My goal is to r ...

Is it possible for me to use an NPX tool to execute git clone command?

I am currently working on developing a personalized NPX tool that will install my custom npm package onto a locally hosted server. At the moment, I have a layout template that I want other users to replicate when they run my NPX command. Here is an exampl ...

Implementing a delay using setTimeOut function to execute an action upon user input

Take a look at this code snippet: $("#test").on("keyup", (e) => { if(e.target.value.length === 3) { setTimeout(() => { console.log("fired") }, 2000) } }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.m ...

javascript image click activates checkbox with PHP support

Is it possible to add a feature that allows clicking on the displayed image to check the checkbox above? I'm having trouble with lines 29-32. Although I found an example, it didn't work for me. Thanks <html> <head> <title&g ...

Locate a specific text within a complex array of objects and retrieve the objects that contain the match as

I have an array of objects named input as shown below. Each object in the array contains a property vertical of type string, an array called platformList, and a nested object named radar_metadata. I am looking to implement a search functionality where I c ...

Difficulty encountered with document.querySelectorAll retrieving paginated elements

I am currently developing a project called STEEP. Our implementation involves utilizing infinite scroll to load 8 videos at a time as the user scrolls through the page. However, we are facing an issue with the script responsible for handling video playbac ...

Navigating a Frame and Clicking a Link with Puppeteer: A Step-by-Step Guide

I am facing an issue with clicking on an anchor link within a page that is supposed to open a new tab for exporting a PDF. The problem arises because this link is located inside a frame within a frameset structure as shown below: https://i.stack.imgur.com ...

Unlocking the potential of a singular item within an ng-repeat generated assortment using AngularJS

After successfully generating a list of items using ng-repeat, I found myself facing another challenge. I am currently trying to access and update a specific element within the collection, but I'm struggling with finding the right approach. Can anyone ...

Emit data asynchronously upon returning

In my node.js application, I have a background process implemented using the EventEmitter. Here is a snippet of how it is used: var event = { returnValue: undefined }; eventEmitter.emit('name', event, argument); return event.returnValue; // This ...