Reputation: 27
I have one array of dates, and one array of objects. Each have a date property. I need to cumulatively sort the objects by date. So, for every date in the date array, I would like to create a cumulative object with every object who's date property is previous to the date in the date array.
For example, the following date array and object array:
['2017-11-5', '2018-3-1', '2018-3-22']
[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]
The desired output would be:
[{name: 'Jes', date: '2017-11-2'}]
[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}]
[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]
I am trying to do this with approximately 500 dates and 30,000 objects.
Here is a current code snippet, but I am having issues with performance, due to the number of objects I am iterating through.
_.each(dtArray,function(i:Date){
let dt = new Date(i);
let filtered = _.filter(data,function(row){
let dtVal = new Date(row['date']);
return dtVal<=dt;
});
Upvotes: 0
Views: 411
Reputation: 56
There are several ways you can improve your algorithm while keeping the associative indices in :
people
and dates
dates
in an ascending mannerdates
and people
indices to keep the original orderremaining
and lastChunk
to reduce remaining
size if people[i].date < dates[j]
The algorithm code:
function filter(dates, people){
let lastChunk = [];
let remaining = people;
let results = [];
// precalculate dates, preserve indexes and sort by date
let sortedDates = dates
.map((value, index) => {
return {
date: new Date(value),
index: index
};
})
.sort((a, b) => {
return a.date<b.date?-1:a.date==b.date?0:1;
});
let peopleWithDates = people.map((value, index) => {
value.dateObject = new Date(value.date);
value.index = index;
return value;
});
for(const i in sortedDates){
const comp = sortedDates[i].date
remaining = remaining.filter((value, index) => {
if(value.dateObject<=comp){
let itemIndex = value.index;
delete value.dateObject;
delete value.index;
lastChunk.splice(itemIndex, 0, value);
return false;
}else{
return true;
}
});
results[sortedDates[i].index] = [...lastChunk];
}
return results;
}
Upvotes: 0
Reputation: 92481
You can map()
over the dates since you want one result array for each date. Then within the map you can filter()
the people based on the date to create that array:
let dates = ['2017-11-5', '2018-3-1', '2018-3-22']
let people = [{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]
let cumul = dates.map(d => people.filter(person => person.date <= d))
console.log(JSON.stringify(cumul, null, 2))
Upvotes: 2