I am currently learning lodash and moment.js and I'm using some dummy data.The dummy data that contains a list of 1000 doctors.I have started working with Array.prototype.map() and Array.prototype.filter() and will be converting them to lodash soon.
data
var doctors = [
{
"id": 0,
"dateOfEmployment": "2012-12-27",
"dateOfTermination": "2015-01-13",
"dateOfBirth": "1978-06-06",
"gender": "Male"
},
{
"id": 1,
"dateOfEmployment": "2016-02-08",
"dateOfTermination": null,
"dateOfBirth": "1984-04-21",
"gender": "Female"
},
{
"id": 2,
"dateOfEmployment": "2010-11-30",
"dateOfTermination": "2015-09-03",
"dateOfBirth": "1975-09-24",
"gender": "Male"
},
{
"id": 3,
"dateOfEmployment": "2012-06-17",
"dateOfTermination": null,
"dateOfBirth": "1980-08-31",
"gender": "Female"
},..];
I would like to get a result of array for the last 2 years:
[{ date: '2015-04', count: 22 },
{ date: '2015-05', count: 25 },
...]
Initially I tried this:
doctors = doctors.filter(function(doctor){
return moment(doctor.dateOfEmployment).isBetween('2014-04', '2016-04');
}).map(function(doctor){
return {
dates: moment(doctor.dateOfEmployment).format('YYYY-MM'),
count: new Date(doctor.dateOfEmployment) - new Date(doctor.dateOfEmployment) + 1 };
}););
console.log(doctors);
I am confused. Should I first create a new array of doctors with just id, dateOfEmployment, dateOfTermination and momentize both dates. Then filter the new date array with a condition where moment isBetween the years and then map/reduce.
I did think of brute-force method where I would loop through 24 times on each doctor and increment a counter based on the condition that if doctorsEmployment date and doctorsTermination date is either null or equal to the temporary date.The temporary date starting from '2014-04' to '2016-04' and finally pushing it to array the result object.
Am I approaching this problem in a wrong way?
Any help will be greatly appreciated!
Not lodash or moment.js, but here's how to do it in plain JS:
// Sample data
var doctors = [
{
"id": 0,
"dateOfEmployment": "2012-12-27",
"dateOfTermination": "2015-01-13",
"dateOfBirth": "1978-06-06",
"gender": "Male"
},
{
"id": 1,
"dateOfEmployment": "2016-02-08",
"dateOfTermination": null,
"dateOfBirth": "1984-04-21",
"gender": "Female"
},
{
"id": 2,
"dateOfEmployment": "2016-02-29",
"dateOfTermination": "2015-09-03",
"dateOfBirth": "1975-09-24",
"gender": "Male"
},
{
"id": 3,
"dateOfEmployment": "2015-06-17",
"dateOfTermination": null,
"dateOfBirth": "1980-08-31",
"gender": "Female"
}];
// Parse ISO date string (e.g. 2016-04-01) as local
function parseISODate(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]? b[1] - 1 : 0, b[2] || 1);
}
var startDate = parseISODate('2014-04'),
endDate = parseISODate('2016-04');
// Creates an object with months and counts
var resultObj = doctors.reduce(function(acc, cur) {
var d = parseISODate(cur.dateOfEmployment);
if (d >= startDate && d <= endDate) {
var month = d.toISOString().slice(0,7);
acc[month] = (acc[month] || 0) + 1;
}
return acc;
}, {});
// Creates an array with required objects from result object
var resultArr = Object.keys(resultObj).map(function(key) {
return {date: key, count: resultObj[key]};
})
document.write(
JSON.stringify(resultObj) + '<br>' + // {"2016-02":2,"2015-06":1}
JSON.stringify(resultArr) // [{"date":"2016-02","count":2},{"date":"2015-06","count":1}]
);
This assumes you only want months that have a count greater than zero. It goes through the original data once, then the result object once, though I can't see how the array is a more desirable format than the object it's created from.
Note that I edited the source data to have two dateOfEmployment dates in February, 2016.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With