field_compactor.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use strict';
  2. function buildRange(item) {
  3. return {
  4. start: item,
  5. count: 1
  6. };
  7. }
  8. function completeRangeWithItem(range, item) {
  9. range.end = item;
  10. range.step = item - range.start;
  11. range.count = 2;
  12. }
  13. function finalizeCurrentRange(results, currentRange, currentItemRange) {
  14. if (currentRange) {
  15. // Two elements do not form a range so split them into 2 single elements
  16. if (currentRange.count === 2) {
  17. results.push(buildRange(currentRange.start));
  18. results.push(buildRange(currentRange.end));
  19. } else {
  20. results.push(currentRange);
  21. }
  22. }
  23. if (currentItemRange) {
  24. results.push(currentItemRange);
  25. }
  26. }
  27. function compactField(arr) {
  28. var results = [];
  29. var currentRange = undefined;
  30. for (var i = 0; i < arr.length; i++) {
  31. var currentItem = arr[i];
  32. if (typeof currentItem !== 'number') {
  33. // String elements can't form a range
  34. finalizeCurrentRange(results, currentRange, buildRange(currentItem));
  35. currentRange = undefined;
  36. } else if (!currentRange) {
  37. // Start a new range
  38. currentRange = buildRange(currentItem);
  39. } else if (currentRange.count === 1) {
  40. // Guess that the current item starts a range
  41. completeRangeWithItem(currentRange, currentItem);
  42. } else {
  43. if (currentRange.step === currentItem - currentRange.end) {
  44. // We found another item that matches the current range
  45. currentRange.count++;
  46. currentRange.end = currentItem;
  47. } else if (currentRange.count === 2) { // The current range can't be continued
  48. // Break the first item of the current range into a single element, and try to start a new range with the second item
  49. results.push(buildRange(currentRange.start));
  50. currentRange = buildRange(currentRange.end);
  51. completeRangeWithItem(currentRange, currentItem);
  52. } else {
  53. // Persist the current range and start a new one with current item
  54. finalizeCurrentRange(results, currentRange);
  55. currentRange = buildRange(currentItem);
  56. }
  57. }
  58. }
  59. finalizeCurrentRange(results, currentRange);
  60. return results;
  61. }
  62. module.exports = compactField;