1

If I have an object with store information that looks like this.

storeHours:
0:
 day: Sunday
 Open: 9:00am
 close: 6:00pm
0:
 day: Monday
 Open: 8:00am
 close: 10:00pm
0:
 day: Tuesday
 Open: 8:00am
 close: 10:00pm
0:
 day: Wednesday
 Open: 8:00am
 close: 10:00pm
0:
 day: Thursday
 Open: 8:00am
 close: 10:00pm
0:
 day: Friday
 Open: 8:00am
 close: 10:00pm
0:
 day: Saturday
 Open: 9:00am
 close: 6:00pm

What function should I write to get output that would give me

simplestoreHours:
0:
 Days: Monday-Friday
 open: 8:00am
 close: 6:00pm 
1: 
 Days: Saturday-Sunday
 open: 9:00am
 close: 6:00pm

Also all the times are formatted momentjs objects so it is possible to use momentjs.

My initial thought is to do a loop and have each element checked against each other. If the open and closing times are the same then just connect the days, but I don't think this very clever.

grasshopper
  • 918
  • 4
  • 13
  • 29
  • Hmmm: loop the elements, you immediately add the first one to object `list` (which contains a list of days, and 1 open+1 close time), then for each consecutive item in the loop you check if it has the same open/close as one in the `list`. If so, you add it to that item, if not you add a new record in `list` – Flame Sep 02 '14 at 10:32
  • @grasshopper, have you tried any offered solutions ? If any meets your requirements please mark answer as correct – Evgeniy Sep 04 '14 at 06:16
  • @Evgeniy thank you for commenting to remind me, the function worked perfectly I used an ng-switch on the front end to get outputs like "All week", "weekdays", and "Weekends" – grasshopper Sep 04 '14 at 06:35
  • Np, glad to help, if you need to update `Days` text like 'Saturday-Sunday' -> 'Weekends' you can use helper object like `var shortStr = { 'Saturday-Sunday' : 'weekends', 'Monday-Friday': 'weekdays','Monday-Sunday': 'All week' }` and update Days: [..] on last iteration like `Days: shortStr[[memo.days[key][0].name, memo.days[key][memo.days[key].length-1 ].name].join('-')]` – Evgeniy Sep 04 '14 at 06:48

2 Answers2

2

reduce Array method can help you.

  1. we have to iterate over initial dates object.
  2. group days and working hours into 2 helper arrays by key. i used concatenated open and close time
  3. keep open and close time in ranges sub array
  4. as we are not sure initial array sorted by day of week i've added day index into days grouped array.
  5. on last iteration lets come through ranges we have and find days with range key, sort it, create Days property as concationation first and last sorted days array and save combined object.

    var groupedObject = obj.reduce(function (memo, item, i, array) {
        var key = item.open+item.close;
    
        memo.ranges[key] = memo.ranges[key] || {};
        memo.days[key] = memo.days[key] || [];
    
        memo.ranges[key] = { open: item.open, close: item.open };
    
        memo.days[key].push({
            index: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'].indexOf(item.day),
            name: item.day
        })
    
        if (i == array.length-1 ) {
            for (var key in memo.ranges) {
                if (memo.ranges.hasOwnProperty(key)) {
    
                    memo.days[key].sort(function(a,b) { return a.index - b.index });
    
                    memo.grouped.push({
                        Days: [
                            memo.days[key][0].name, 
                            memo.days[key][memo.days[key].length-1 ].name
                        ].join('-'),
                        open: memo.ranges[key].open,
                        close: memo.ranges[key].close
                    });
                }
            }
        }
    
      return memo
    
    }, { ranges: {}, days: {}, grouped: [] });
    
    console.log(groupedObject.grouped);
    

thats it)

Evgeniy
  • 2,915
  • 3
  • 21
  • 35
0

You could do it this way:

var storeHours = [
    {day: 'Sunday', open: '9:00am', close: '6:00pm' },
    {day: 'Monday', open: '8:00am', close: '10:00pm' },
    {day: 'Tuesday', open: '8:00am', close: '10:00pm' },
    {day: 'Wednesday', open: '8:00am', close: '10:00pm' },
    {day: 'Thursday', open: '8:00am', close: '10:00pm' },
    {day: 'Friday', open: '8:00am', close: '10:00pm' },
    {day: 'Saturday', open: '9:00am', close: '6:00pm' }
];

function sort() {

var daysSorted = [];

for (var dayCounter = 0, length = storeHours.length; dayCounter < length; dayCounter++)     {

    var open = storeHours[dayCounter].open,
        close = storeHours[dayCounter].close,
        name = storeHours[dayCounter].day,
        found = false;

    for (var sortedDayCounter = 0, lengthSorted = daysSorted.length; sortedDayCounter < lengthSorted; sortedDayCounter++) {

        var sortedOpen = daysSorted[sortedDayCounter].open,
            sortedClose = daysSorted[sortedDayCounter].close;

        if (sortedOpen === open && sortedClose == close) {

            daysSorted[sortedDayCounter].day += ', ' + name;
            found = true;

        }

    };

    if (!found) {
        daysSorted.push(storeHours[dayCounter]);
    }

};

return daysSorted;

}

console.log(sort());

Anyway, I recommend that you consider open and close dates as Date types, rather than strings.

Hope this helps,