7
\$\begingroup\$

I want to create a "timetable" for some shop. It should look like, "days - hours".

I get response from the server in this way:

var array = [{
  days : ["Mo", "Tu", "We", "Th", "Sa"],
  dayIndexes: [1,2,3,4, 6],
  time: "9am - 3pm"
}, {
  days : ["Mo", "Tu", "We", "Th", "Sa"],
  dayIndexes: [1,2,3,4,6],
  time: "5pm - 9pm"
}, {
  days : ["Fr", "Su"],
  dayIndexes: [5,7],
  time: "9am - 2pm"
}];

It is like one object contains days for which shop has the same work hours. Duplicates by property days can happen because it is how the server implement "breaks" for a shop.

I've added my working sample, which returns exactly what I need, but I think it can be made simpler.

jsFiddle


var array = [{
     days: ["Mo", "Tu", "We", "Th", "Sa"],
     dayIndexes: [1, 2, 3, 4, 6],
     time: "9am - 3pm"
 }, {
     days: ["Mo", "Tu", "We", "Th", "Sa"],
     dayIndexes: [1, 2, 3, 4, 6],
     time: "5pm - 9pm"
 }, {
     days: ["Fr", "Su"],
     dayIndexes: [5, 7],
     time: "9am - 2pm"
 }];
 var convertToRanges = function(arr) {
     console.log(arr);
     if (arr.length > 0) {
         var ranges = [
                 [arr[0], arr[0]]
             ],
             lastIndex = 0;

         for (var i = 1; i < arr.length; i++) {
             if (arr[i] - ranges[lastIndex][1] === 1) {
                 ranges[lastIndex][1] = arr[i];
             } else {
                 ranges[++lastIndex] = [arr[i], arr[i]];
             }
         }

         var res = ranges.map((item) => {
             if (item[0] !== item[item.length - 1]) {
                 return moment.weekdaysShort(item[0]) + '-' + moment.weekdaysShort(item[item.length - 1]);
             } else {
                 return moment.weekdaysShort(item[0]);
             }
         });
     } else {
         res = moment.weekdaysShort(arr[0]);
     }

     return res.join(', ');
 }

 var result = _(array)
     .groupBy('dayIndexes')
     .map(function(days) {
         return _.mergeWith.apply(_, [{}].concat(days).concat([
             function(obj, src, key) {
                 if (key === 'time' && obj && src) {
                     return [obj, src].join(', ');
                 }
             }
         ]));
     })
     .values()
     .value()
     .map(d => {
         d.days = convertToRanges(d.dayIndexes);
         return d;
     });

 console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>

\$\endgroup\$
0
1
\$\begingroup\$

A review mostly focusing on style:

  • Avoid calls to console.log in clean code (it's okay for debugging, but should be removed afterwards)
  • Try not to declare variables in for statements ( the variable is accessible to the whole function anyway). Try to declare variables on top
  • Your code could use more comments, especially this part which was hardest to parse/grok:

         if (arr[i] - ranges[lastIndex][1] === 1) {
             ranges[lastIndex][1] = arr[i];
         } else {
             ranges[++lastIndex] = [arr[i], arr[i]];
         }
    

Other than that there is not much wrong with the code, I tried to write it in a more elegant way, but found my attempts usually longer and not that much more elegant.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.