Search code examples
javascriptarraysstringjavascript-objects

Generate day-of-the-week objects from an array of strings


I have an array of day ranges, like this:

["Mon-Tue", "Mon-Wed", "Mon-Thu", "Mon-Fri", "Mon-Sat", "Mon-Sun", "Tue-Mon", "Tue-Wed", "Tue-Thu", "Tue-Fri", "Tue-Sat", "Tue-Sun", ...]

What I need is to create a large object which maps each one of these strings to an array containing all the relevant days, like this:

var object = {
  'Mon-Tue': ['Mon', 'Tue'],
  'Mon-Wed': ['Mon', 'Tue', 'Wed'],
}

To help, I have an array of the possible days:

var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

Is this possible without doing it all manually?

Thanks!


Solution

  • You could take a Map for getting days with an index and iterate until you got all days.

    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        daysMap = new Map(days.map((d, i) => [d, i])),
        data = ["Mon-Tue", "Mon-Wed", "Mon-Thu", "Mon-Fri", "Mon-Sat", "Mon-Sun", "Tue-Mon", "Tue-Wed", "Tue-Thu", "Tue-Fri", "Tue-Sat", "Tue-Sun"],
        result = Object.assign({}, ...data.map(d => {
            var [start, end] = d.split('-'),
                temp = [],
                s = daysMap.get(start),
                e = daysMap.get(end);
    
            while (s !== e) {
                temp.push(days[s]);
                s++;
                s %= days.length
            }
            temp.push(days[s]);
            return { [d]: temp };
        }));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    If you like, you could take a Generator for the wanted days.

    function* getDays(from, to) {
        var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
            i = days.indexOf(from);
    
        while (days[i % days.length] !== to) yield days[i++ % days.length];
        yield days[i % days.length];
    }
    
    var data = ["Fri-Tue", "Mon-Tue", "Mon-Wed", "Mon-Thu", "Mon-Fri", "Mon-Sat", "Mon-Sun", "Tue-Mon", "Tue-Wed", "Tue-Thu", "Tue-Fri", "Tue-Sat", "Tue-Sun"],
        result = Object.assign({}, ...data.map(d => ({ [d]: [...getDays(...d.split('-'))] })));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    Another approach by using a tomorrow object, which gives the day of tomorrow.

    function* getDays(from, to) {
        var tomorrow = { Sun: 'Mon', Mon: 'Tue', Tue: 'Wed', Wed: 'Thu', Thu: 'Fri', Fri: 'Sat', Sat: 'Sun' };
    
        yield from;
        while (from !== to) yield from = tomorrow[from];
    }
    
    var data = ["Fri-Tue", "Mon-Tue", "Mon-Wed", "Mon-Thu", "Mon-Fri", "Mon-Sat", "Mon-Sun", "Tue-Mon", "Tue-Wed", "Tue-Thu", "Tue-Fri", "Tue-Sat", "Tue-Sun"],
        result = Object.assign({}, ...data.map(d => ({ [d]: [...getDays(...d.split('-'))] })));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }