1

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.

4
  • please include something you tried within your question Commented May 31, 2020 at 8:35
  • So what should the final array be like after merging/removing duplicates for the given example above? Commented May 31, 2020 at 8:39
  • Please edit your question and include the expected output with proper code formatting Commented May 31, 2020 at 8:41
  • 1
    Does this answer your question? Remove duplicate values from JS array. Checkout the section "Unique by..." of the this answer. Commented May 31, 2020 at 8:50

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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);

3 Comments

do you mind explaining the following syntax - [${period.openTime}-${period.closeTime}]?
@devinthemaking I have added some comments to my code.
but what if I want exact matches - I mean only I want to "merge" them if all periods are the same of each day?
0

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);

1 Comment

if I have only one period per day it works correct, however when periods is 2+ I get "Cannot read property 'openTime' of undefined"". @gorak
0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.