0

I've an array which contains the data of users joined in last seven days from current date. e.g. users=['19 Dec', '21 Dec', '21 Dec'] In this array, three users joined in last 7 days. I'm trying to find the unique occurence with this function. `

 let occurences = users.reduce(function (acc, curr) {
              return acc[curr] ? ++acc[curr] : (acc[curr] = 1), acc;
            }, {});

`

It's returning the object that contains the following key-pairs: {19 Dec: 1, 21 Dec: 2} I'm expecting to fill the missing values in the object with 0 and with it's respective date. So, the final O/P will be : {19 Dec: 1, 20 Dec: 0, 21 Dec: 2, 22 Dec: 0, 23 Dec: 0, 24 Dec: 0, 25 Dec: 0}

Can someone please help me out to solve this?

I'm expecting to fill the missing values in the object with 0 and with it's respective date. So, the final O/P will be : {19 Dec: 1, 20 Dec: 0, 21 Dec: 2, 22 Dec: 0, 23 Dec: 0, 24 Dec: 0, 25 Dec: 0}

  • ```reduce``` is an array method, using ```reduce``` on ```users[1]```, won't return anything. Try checking it again. – Yash Sharma Dec 25 '22 at 10:39
  • Hey Yash, There was an error in my code, it was users.reduce not users[1].reduce. Even then, how will I do it? – Nitin Saini Dec 25 '22 at 10:45

3 Answers3

0

Perhaps something like this will work for you. I'm using a modified version of the code found in this SO answer. The formatting was done thanks to this SO answer.

First, let's build an array containing the last 7 days.

Date.prototype.addDays = function(days) {
    var date = new Date(this.valueOf());
    date.setDate(date.getDate() + days);
    return date;
}

function getDates(startDate, stopDate) {
    var dateArray = [];
    var currentDate = startDate;
    while (currentDate <= stopDate) {
        var calendarDay = currentDate.getDate();
        var monthName = new Intl.DateTimeFormat('en-US', options).format(currentDate);
        dateArray.push(calendarDay + " " + monthName);
        currentDate = currentDate.addDays(1);
    }
    return dateArray;
}

var options = { month: 'short' };
var end = new Date();
var start = end.addDays(-7);

var dateArray = getDates(start,end);

Next, let's assume that this is your JSON object with date - short month names as keys, and number of non-zero users as values.

let occurences = {
    "19 Dec": 1,
    "21 Dec": 2
};

We'll make a working copy of it, which we'll then modify as needed. You don't have to do this - you can declare occurences differently, and modify it instead, but I'm doing it with the copy.

var copyOcc = occurences;

Next, we'll loop through our dateArray, and check if there's a key in occurences corresponding to the current value from dateArray.

for(var i = 0; i < dateArray.length; i++) {
    // If the key isn't there, add it
    if(!copyOcc.hasOwnProperty(dateArray[i])) {
        copyOcc[dateArray[i]] = 0;
    }
}

console.log(copyOcc);

This will output:

{
  18 Dec: 0,
  19 Dec: 1,
  20 Dec: 0,
  21 Dec: 2,
  22 Dec: 0,
  23 Dec: 0,
  24 Dec: 0,
  25 Dec: 0
}

See the following fiddle for the complete script.

FiddlingAway
  • 1,598
  • 3
  • 14
  • 30
0

I suggest the following solution, written in typescript:

  1. Create an array containing the last 7 days, formatted according to the dates in users-array.
  2. Iterate through the last 7 dates (using the map-operator) and apply filter for each day to find out how many users joined on the given day.
  3. getDailyRegistrations() will return and object with the dates as keys and the number of user-registrations on a given day as value.
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
users = ['19 Dec', '21 Dec', '21 Dec'];


getDailyRegistrations(numberOfDays: number = 7): any {
    let occurrences: any = {};
    this.getLastXDates(numberOfDays)
        .map(d => this.formatDate(d))
        .forEach((d: string) => {
            occurrences[d] = this.users.filter(u => u === d).length;
    });
    return occurrences;
}


/* Helper methods */

private getLastXDates(numbOfDays: number): Date[] {
    return Array.from(Array(numbOfDays).keys()).reverse().map(i => {
        const d = new Date();
        d.setDate(d.getDate() - i);
        return d;
    });
}

private formatDate(d: Date): string {
    const day = d.getDate();
    const month = this.months[d.getMonth()];
    return `${day} ${month}`;
}
kellermat
  • 2,859
  • 2
  • 4
  • 21
0

Same as above answer but in pure javascript.

const users = ['19 Dec', '21 Dec', '21 Dec']
const month_to_abv = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

// fetch previouse days, default it fetches 7 days
function getPreviouseDaysObj(noOfDays = 7) {
  const obj = {};
  for (let i = 0; i < noOfDays; i++) {
    const curr_date = new Date();
    curr_date.setDate(curr_date.getDate() - i);
    obj[formatDate(curr_date)] = 0;
  }
  return obj;
}
// format date
function formatDate(date) {
  return `${date.getDate()} ${month_to_abv[date.getMonth()]}`
}

// create obj for previouse 7 days
const previouse_days = getPreviouseDaysObj(7);

// calculate occurance
const occurences = users.reduce(function (acc, curr) {
  acc[curr] ? ++acc[curr] : (acc[curr] = 1);
  return acc;
}, Object.assign({}, previouse_days));


// Log to console
console.log(occurences)
Daxay Makwana
  • 65
  • 1
  • 5