Reputation: 77
So I have the following structure:
[{
"isOpen": 1,
"weekday": 1,
"humanDay": "Monday",
"periods": [{
"openDay": "Monday",
"openTime": "12:00",
"closeDay": "Monday",
"closeTime": "14:30"
},
{
"openDay": "Monday",
"openTime": "19:00",
"closeDay": "Monday",
"closeTime": "22:30"
},
{
"openDay": "Monday",
"openTime": "23:00",
"closeDay": "Monday",
"closeTime": "23:30"
}
]
},
{
"isOpen": 1,
"weekday": 1,
"humanDay": "Tuesday",
"periods": [{
"openDay": "Tuesday",
"openTime": "12:00",
"closeDay": "Tuesday",
"closeTime": "14:30"
},
{
"openDay": "Tuesday",
"openTime": "19:00",
"closeDay": "Tuesday",
"closeTime": "22:30"
},
{
"openDay": "Tuesday",
"openTime": "23:00",
"closeDay": "Tuesday",
"closeTime": "23:30"
}
]
}
]
What I want to do, is if all periods for a given day are the same as any other day(matching by their openTime and closeTime) in the array to merge them (or just delete the second occurrence). If the periods are of a different length no action will occur. Also if just one of the openTime or closeTime is different, again no action will occur. So far I have tried looping through all days and comparing one with the following after it. Got stuck in comparing the periods. Tried following the explanation here - https://gomakethings.com/check-if-two-arrays-or-objects-are-equal-with-javascript/, but again got lost. The desired output will be:
[{
"isOpen": 1,
"weekday": 1,
"humanDay": "Monday, Tuesday",
"periods": [{
"openDay": "Monday",
"openTime": "12:00",
"closeDay": "Monday",
"closeTime": "14:30"
},
{
"openDay": "Monday",
"openTime": "19:00",
"closeDay": "Monday",
"closeTime": "22:30"
},
{
"openDay": "Monday",
"openTime": "23:00",
"closeDay": "Monday",
"closeTime": "23:30"
}
]
},
As I don't care about changing the openDay/closeDay in the periods. I want to do this check for all days in the array.
Upvotes: 1
Views: 138
Reputation: 206
I hope this will help you out solving your issue. This code will remove duplicate values from periods array from each object. I have copied some periods and tried duplicating the values.
var data = [
{
"isOpen": 1,
"weekday": 1,
"humanDay": "Monday",
"periods":
[
{
"openDay": "Monday",
"openTime": "12:00",
"closeDay": "Monday",
"closeTime": "14:30"
},
{
"openDay": "Monday",
"openTime": "19:00",
"closeDay": "Monday",
"closeTime": "22:30"
}, {
"openDay": "Monday",
"openTime": "19:00",
"closeDay": "Monday",
"closeTime": "22:30"
},
{
"openDay": "Monday",
"openTime": "23:00",
"closeDay": "Monday",
"closeTime": "23:30"
}
]
},
{
"isOpen": 1,
"weekday": 1,
"humanDay": "Tuesday",
"periods":
[
{
"openDay": "Tuesday",
"openTime": "12:00",
"closeDay": "Tuesday",
"closeTime": "14:30"
},
{
"openDay": "Tuesday",
"openTime": "19:00",
"closeDay": "Tuesday",
"closeTime": "22:30"
},
{
"openDay": "Tuesday",
"openTime": "19:00",
"closeDay": "Tuesday",
"closeTime": "22:30"
},
{
"openDay": "Tuesday",
"openTime": "19:00",
"closeDay": "Tuesday",
"closeTime": "22:30"
},
{
"openDay": "Tuesday",
"openTime": "23:00",
"closeDay": "Tuesday",
"closeTime": "23:30"
}
]
}
]
for (const dt of data) {
let pr = [];
for (const period of dt.periods) {
let prIndex = pr.findIndex(p => (p.openTime == period.openTime && p.closeTime == period.closeTime));
if (prIndex == -1) {
pr.push({
"openDay": period.openDay,
"openTime": period.openTime,
"closeDay": period.closeDay,
"closeTime": period.closeTime
});
}
}
dt.periods = pr;
}
console.log(data);
Upvotes: 0
Reputation: 5308
You can sum up the entire process inside reduce
method:
var data = [{ "isOpen":1, "weekday":1, "humanDay":"Monday", "periods": [ { "openDay":"Monday", "openTime":"12:00", "closeDay":"Monday", "closeTime":"14:30" }, { "openDay":"Monday", "openTime":"19:00", "closeDay":"Monday", "closeTime":"22:30" }, { "openDay":"Monday", "openTime":"23:00", "closeDay":"Monday", "closeTime":"23:30" } ]},{ "isOpen":1, "weekday":1, "humanDay":"Tuesday", "periods": [ { "openDay":"Tuesday", "openTime":"12:00", "closeDay":"Tuesday", "closeTime":"14:30" }, { "openDay":"Tuesday", "openTime":"19:00", "closeDay":"Tuesday", "closeTime":"22:30" }, { "openDay":"Tuesday", "openTime":"23:00", "closeDay":"Tuesday", "closeTime":"23:30" } ]}];
var result = Object.values(data.reduce((acc, elem, i, self)=>{
otherDays = self.filter(k=>k.periods.every((d,j)=>d.openTime == elem.periods[j].openTime && d.closeTime == elem.periods[j].closeTime));
key = otherDays.map(({humanDay})=>humanDay).join(',');
acc[key] = acc[key] || {...elem, humanDay:key};
return acc;
},{}));
console.log(result);
Upvotes: 0
Reputation: 12737
I understand what you are trying to do. And I also noticed that your output might be a little bit confusing, since you are reducing the duplicates from the outer level of the array (by joining the humanDay names) but keeping the inner (openDay closeDay) tags.
I have re-written how the output should be like, and also, joined weekday names in an array for more convenience.
let timings = [{
isOpen: 1,
weekday: 1,
humanDay: "Monday",
periods: [{
openDay: "Monday",
openTime: "12:00",
closeDay: "Monday",
closeTime: "14:30",
},
{
openDay: "Monday",
openTime: "19:00",
closeDay: "Monday",
closeTime: "22:30",
},
{
openDay: "Monday",
openTime: "23:00",
closeDay: "Monday",
closeTime: "23:30",
},
],
},
{
isOpen: 1,
weekday: 1,
humanDay: "Tuesday",
periods: [{
openDay: "Tuesday",
openTime: "12:00",
closeDay: "Tuesday",
closeTime: "14:30",
},
{
openDay: "Tuesday",
openTime: "19:00",
closeDay: "Tuesday",
closeTime: "22:30",
},
{
openDay: "Tuesday",
openTime: "23:00",
closeDay: "Tuesday",
closeTime: "23:30",
},
],
},
];
// create an empty object
const weekdays = {};
timings.forEach((timing) => {
timing.periods.forEach((period) => {
// check if the object has a key matching
// the openTime to CloseTime string
// (this can be any key, but we want to capture all
// .. days that have the same open and close times)
if (!weekdays[`${period.openTime}-${period.closeTime}`]) {
// the key does not exist, so lets create an new sub-object for
// that given key, and prepare its array of days:
weekdays[`${period.openTime}-${period.closeTime}`] = {
days: [],
};
}
// now, add the current day to the pre-defined sub-array:
weekdays[`${period.openTime}-${period.closeTime}`].days.push(
timing.humanDay
);
// also, store the openTime and closeTime as sub-properties, for convenience
// i know they are stored in the key but the whole purpose of the key
// is to reduce duplicates by taking advantage of javascript built in
// funcationalities.
weekdays[`${period.openTime}-${period.closeTime}`]["openTime"] =
period.openTime;
weekdays[`${period.openTime}-${period.closeTime}`]["closeTime"] =
period.closeTime;
});
});
console.log(weekdays);
Upvotes: 0
Reputation: 311
You just need a function that will compare the two objects Also, as you want an array with no duplicates, its probably a good idea to test for duplicates before adding to the array.
function CompareSchedule(s1, s2) {
return s1.openTime == s2.openTime && s1.closeTime == s2.closeTime;
}
function AddToArray(s) {
for (var i = 0; i < schedules.length; i++) {
if (CompareSchedule(s, schedules[i]))
return false;
}
schedules.push(s);
return true;
}
You can then change your Compare method if you need additional checks etc.
Upvotes: 1