65 lines
1.7 KiB
JavaScript
65 lines
1.7 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
// rangeFormat :: [Int] -> String
|
|
var rangeFormat = function (xs) {
|
|
return splitBy(function (a, b) {
|
|
return b - a > 1;
|
|
}, xs)
|
|
.map(rangeString)
|
|
.join(',');
|
|
};
|
|
|
|
// rangeString :: [Int] -> String
|
|
var rangeString = function (xs) {
|
|
return xs.length > 2 ? [head(xs), last(xs)].map(show)
|
|
.join('-') : xs.join(',');
|
|
};
|
|
|
|
// GENERIC FUNCTIONS
|
|
|
|
// Splitting not on a delimiter, but whenever the relationship between
|
|
// two consecutive items matches a supplied predicate function
|
|
|
|
// splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
|
|
var splitBy = function (f, xs) {
|
|
if (xs.length < 2) return [xs];
|
|
var h = head(xs),
|
|
lstParts = xs.slice(1)
|
|
.reduce(function (a, x) {
|
|
var acc = a[0],
|
|
active = a[1],
|
|
prev = a[2];
|
|
|
|
return f(prev, x) ? (
|
|
[acc.concat([active]), [x], x]
|
|
) : [acc, active.concat(x), x];
|
|
}, [
|
|
[],
|
|
[h], h
|
|
]);
|
|
return lstParts[0].concat([lstParts[1]]);
|
|
};
|
|
|
|
// head :: [a] -> a
|
|
var head = function (xs) {
|
|
return xs.length ? xs[0] : undefined;
|
|
};
|
|
|
|
// last :: [a] -> a
|
|
var last = function (xs) {
|
|
return xs.length ? xs.slice(-1)[0] : undefined;
|
|
};
|
|
|
|
// show :: a -> String
|
|
var show = function (x) {
|
|
return JSON.stringify(x);
|
|
};
|
|
|
|
// TEST
|
|
return rangeFormat([0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16,
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32,
|
|
33, 35, 36, 37, 38, 39
|
|
]);
|
|
})();
|