I'm trying to solve a scheduling problem in my API, and I'm having some doubts in the manipulation of array of objects. I created a logic that returns dates that are different from those that are busy, but I can't solve the time issue. I have this array called listDates:
listDates =
[
{
"date": "01/05/2022",
"hour": [
"7:30:00",
"8:00:00",
"8:30:00",
"9:00:00",
"9:30:00",
"10:00:00",
"10:30:00",
"11:00:00",
"11:30:00",
"12:00:00",
"12:30:00",
"13:00:00",
"13:30:00",
"14:00:00",
"14:30:00",
"15:00:00",
"15:30:00",
"16:00:00",
"16:30:00",
"17:00:00"
]
},
{
"date": "02/05/2022",
"hour": [
"7:30:00",
"8:00:00",
"8:30:00",
"9:00:00",
"9:30:00",
"10:00:00",
"10:30:00",
"11:00:00",
"11:30:00",
"12:00:00",
"12:30:00",
"13:00:00",
"13:30:00",
"14:00:00",
"14:30:00",
"15:00:00",
"15:30:00",
"16:00:00",
"16:30:00",
"17:00:00"
]
},
...
]
And I want to filter out everything that is different from this array called occupiedDateHour:
occupiedDateHour =
[
{
"date": "02/05/2022",
"hour": [
"16:00:00"
]
},
{
"date": "01/05/2022",
"hour": [
"14:00:00"
]
}
]
I need something like:
newListDates =
[
{
"date": "01/05/2022",
"hour": [
"7:30:00",
"8:00:00",
"8:30:00",
"9:00:00",
"9:30:00",
"10:00:00",
"10:30:00",
"11:00:00",
"11:30:00",
"12:00:00",
"12:30:00",
"13:00:00",
"13:30:00",
"14:30:00",
"15:00:00",
"15:30:00",
"16:00:00",
"16:30:00",
"17:00:00"
]
},
{
"date": "02/05/2022",
"hour": [
"7:30:00",
"8:00:00",
"8:30:00",
"9:00:00",
"9:30:00",
"10:00:00",
"10:30:00",
"11:00:00",
"11:30:00",
"12:00:00",
"12:30:00",
"13:00:00",
"13:30:00",
"14:00:00",
"14:30:00",
"15:00:00",
"15:30:00",
"16:30:00",
"17:00:00"
]
},
...
]
If all times for a certain date have been occupied, it will not even return that specific date. The logic to return dates I wrote:
newListDates = listDates.filter(function (arr) {
return occupiedDateHour.some(function (f) {
return f.date === arr.date
});
});
CodePudding user response:
You can use a combination of Array#reduce
, Array#map
and Array#filter
as in the following demo:
const listDates = [ { "date": "01/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] }, { "date": "02/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] } ],
occupiedDateHour = [ { "date": "02/05/2022", "hour": [ "16:00:00" ] }, { "date": "01/05/2022", "hour": [ "14:00:00" ] } ],
obj = occupiedDateHour.reduce((acc,{date,hour}) => ({...acc,[date]:hour}),{}),
output = listDates.map(
({ date, hour }) =>
({
date,
hour: hour.filter(h => !(obj[date] || []).includes(h))
})
);
console.log( output );
CodePudding user response:
You can try map
and find
with some logic to handle filters
const listDates=[{"date":"01/05/2022","hour":["7:30:00","8:00:00","8:30:00","9:00:00","9:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00","12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00","17:00:00"]},{"date":"02/05/2022","hour":["7:30:00","8:00:00","8:30:00","9:00:00","9:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00","12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00","17:00:00"]},]
const occupiedDateHour=[{"date":"02/05/2022","hour":["16:00:00"]},{"date":"01/05/2022","hour":["14:00:00"]}]
const newListDates = listDates.map((currentDateData) => {
const currentOccupiedDateHour = occupiedDateHour.find(dateData => dateData.date === currentDateData.date)
if (!currentOccupiedDateHour) {
return currentDateData
}
return {
date: currentDateData.date,
hour: currentDateData.hour.filter(currentHour => !currentOccupiedDateHour.hour.includes(currentHour))
}
})
console.log(newListDates)
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
I'd start by transforming occupiedDateHour
into an object which is better suited for the filtering:
const occupiedDateHour = [
{ "date": "02/05/2022", "hour": ["16:00:00"] },
{ "date": "01/05/2022", "hour": ["14:00:00"] }
];
const occupiedDateHourIndex = occupiedDateHour.reduce((acc, el) => {
acc[el.date] = el.hour;
}, {});
producing a structure like this:
{
"02/05/2022" : ["16:00:00"], "01/05/2022": ["14:00:00"]
}
Add a filtering function:
const filterHours = (hours, excludeHours) => {
return hours.filter(h => !excludeHours.includes(h));
};
With that, you can do an O(1) lookup of the list of hours to exclude for a given date; and filter the hours of a given date by that exclusion list.
Apply the filter and you're done:
const newListDates = listDates.map(el => {
const date = el.date;
const hour = filterHours(el.hour, occupiedDateHourIndex[date]);
return { date, hour }
})
Demo...
const occupiedDateHour = [
{
"date": "02/05/2022",
"hour": ["16:00:00"]
},
{
"date": "01/05/2022",
"hour": ["14:00:00"]
}
];
const occupiedDateHourIndex = occupiedDateHour.reduce((acc, el) => {
acc[el.date] = el.hour;
return acc;
}, {});
const filterHours = (hours, excludeHours) => {
return hours.filter(h => !excludeHours.includes(h));
};
const listDates = [ { "date": "01/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] }, { "date": "02/05/2022", "hour": [ "7:30:00", "8:00:00", "8:30:00", "9:00:00", "9:30:00", "10:00:00", "10:30:00", "11:00:00", "11:30:00", "12:00:00", "12:30:00", "13:00:00", "13:30:00", "14:00:00", "14:30:00", "15:00:00", "15:30:00", "16:00:00", "16:30:00", "17:00:00" ] } ]
const newListDates = listDates.map(el => {
const date = el.date;
const hour = filterHours(el.hour, occupiedDateHourIndex[date]);
return { date, hour }
})
console.log(JSON.stringify(newListDates, null, 4))