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.

  • [please include something you tried](https://stackoverflow.com/help/minimal-reproducible-example) within your question – KooiInc May 31 '20 at 08:35
  • So what should the final array be like after merging/removing duplicates for the given example above? – Ahmad May 31 '20 at 08:39
  • Please edit your question and include the expected output with proper code formatting – Ahmad May 31 '20 at 08:41
  • 1
    Does this answer your question? [Remove duplicate values from JS array](https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array). Checkout the section "Unique by..." of the [this answer](https://stackoverflow.com/a/9229821/3233827). – ssc-hrep3 May 31 '20 at 08:50

4 Answers4

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.

LeiMagnus
  • 253
  • 2
  • 13
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);
Varun Sharma
  • 206
  • 1
  • 9
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);
Ahmad
  • 12,336
  • 6
  • 48
  • 88
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);
gorak
  • 5,233
  • 1
  • 7
  • 19
  • 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 – devinthemaking Jun 01 '20 at 07:56