Comparison between date codes - javascript

I have an array of values as such:
var array_1 = ["1W", "2W", "3W","1M", "2M", "3M", "6M","9M","1Y"]
W stands for weeks, M for months, Y for years. How do I do a string comparison such that a comparison between
"1Y" > "9M"
will return true

You could take the same base, like days for every information and take the letter for an equivalent of days and return the product.
function getDays(string) {
return string.slice(0, -1) * { W: 7, M: 30, Y: 365 }[string.slice(-1)];
}
var array = ["1W", "2W", "3W","1M", "2M", "3M", "6M","9M","1Y"]
console.log(array.map(getDays));

Here is a simple decoder that is easy to expand upon.
In essence it filters the numeric value and then returns it multiplied by some constant based upon the what time symbol it finds in the string (W, M, ...).
function decodeDateCode(dateCode) {
var numeric = parseInt(dateCode.replace(/\D/igm, ''), 10);
if (dateCode.indexOf("D") >= 0) {
return numeric;
}
if (dateCode.indexOf("W") >= 0) {
return numeric * 7;
}
if (dateCode.indexOf("M") >= 0) {
return numeric * (365 / 12);
}
if (dateCode.indexOf("Y") >= 0) {
return numeric * 365;
}
}
//test
var dateCodes = ["1W", "2W", "3W", "1M", "2M", "3M", "6M", "9M", "1Y", "50W"];
//Decode entire list
console.log("Decoded list:", dateCodes.map(decodeDateCode));
//Sort entire list in descending order
console.log("Sorted descending list:", dateCodes.sort(function(a, b) {
return decodeDateCode(b) - decodeDateCode(a);
}));
//Make simple comparison
console.log("Simple comparison:", decodeDateCode("1Y") > decodeDateCode("9M"));

Related

Javascript how to round a whole number up and find its addition value?

Goal
I am at the final stage of scripting a Luhn algorithm.
Problem
Let's say I have a final calculation of 73
How can I round it up to the next 0? So the final value is 80.
And lastly, how can I get the value that made the addition? e.g. 7 is the final answer.
Current code
function validateCred(array) {
// Array to return the result of the algorithm
const algorithmValue = [];
// Create a [2, 1, 2] Pattern
const pattern = array.map((x, y) => {
return 2 - (y % 2);
});
// From given array, multiply each element by it's pattern
const multiplyByPattern = array.map((n, i) => {
return n * pattern[i];
});
// From the new array, split the numbers with length of 2 e.g. 12 and add them together e.g. 1 + 2 = 3
multiplyByPattern.forEach(el => {
// Check for lenght of 2
if(el.toString().length == 2) {
// Split the number
const splitNum = el.toString().split('');
// Add the 2 numbers together
const addSplitNum = splitNum.map(Number).reduce(add, 0);
// Function to add number together
function add(accumalator, a) {
return accumalator + a;
}
algorithmValue.push(addSplitNum);
}
// Check for lenght of 1
else if(el.toString().length == 1){
algorithmValue.push(el);
}
});
// Sum up the algorithmValue together
const additionOfAlgorithmValue = algorithmValue.reduce((a, b) => {
return a + b;
});
// Mod the final value by 10
if((additionOfAlgorithmValue % 10) == 0) {
return true;
}
else{
return false;
}
}
// Output is False
console.log(validateCred([2,7,6,9,1,4,8,3,0,4,0,5,9,9,8]));
Summary of the code above
The output should be True. This is because, I have given the total length of 15 digits in the array. Whereas it should be 16. I know the 16th value is 7, because the total value of the array given is 73, and rounding it up to the next 0 is 80, meaning the check digit is 7.
Question
How can I get the check number if given array length is less than 15?
You could do something like this:
let x = [73,81,92,101,423];
let y = x.map((v) => {
let remainder = v % 10;
let nextRounded = v + (10-remainder);
/* or you could use
let nextRounded = (parseInt(v/10)+1)*10;
*/
let amountToNextRounded = 10 - remainder;
return [nextRounded,amountToNextRounded];
});
console.log(y);
EDIT
As noticed by #pilchard you could find nextRounded using this more simplified way:
let nextRounded = v + (10-remainder);
https://stackoverflow.com/users/13762301/pilchard
I think what you need is this:
var oldNum = 73
var newNum = Math.ceil((oldNum+1) / 10) * 10;;
Then check the difference using this:
Math.abs(newNum - oldNum);

Get non-selected date ranges from the selected date ranges in JavaScript

I have an array of date ranges(selectedRanges) which shows assigned dates for a member between the main date range. I want to know the date ranges where he/she is unassigned. Please refer to the below example.
mainDateRange = ['01-01-2020', '14-06-2020'];
selectedRanges = [
['03-01-2020','04-01-2020'],
['03-01-2020','05-01-2020'], //overlapping dates
['11-01-2020','13-01-2020'],
['01-02-2020','20-02-2020'],
['15-03-2020','18-03-2020'],
['06-01-2020','06-01-2020'], //date ranges will not be ordered
['03-01-2020','04-01-2020']
]; //dates that the member has work assigned
Desired output
excludedRanges = [
['01-01-2020','02-01-2020'],
['07-01-2020','10-01-2020'],
['14-01-2020','31-01-2020'],
['21-02-2020','14-03-2020'],
['19-03-2020','14-06-2020']
]; //shows all the unassigned periods(ranges)
selectedRanges date ranges will have ranges in random order and also may have duplicate and overlapping dates.
I have searched a lot and found nothing. I am only able to get the unselected dates, not as a range. Please help.
Thank you
Interesting problem, I'll propose an approach to achieve this desired behavior by doing the following:
Transform all string dates into date objects.
Sort the selectedRanges array in ascending order using the start and end dates. This sorting step is cricual to finding the date range gaps.
Adding a "moving cursor" date that moves between the mainDateRange to find and add the missing ranges to the output array.
Before we start the date calculations, we'll need a few helper functions. I've added two functions to go back and forth between the date object and the string format you have (dd-mm-yyyy). Please note that you may not need these two helper function if you use something like Moment.js, but I won't impose an extra dependency on your project.
function stringToDate(stringDate) {
const parts = stringDate.split('-').map((p) => parseInt(p));
parts[1] -= 1;
return new Date(...parts.reverse());
}
function dateToString(date) {
return `${('0' + date.getDate()).slice(-2)}-${('0' + (date.getMonth() + 1)).slice(-2)}-${date.getFullYear()}`;
}
I've also added a sorter function that makes sure the ranges are sorted in an ascending fashion (smaller ranges first).
function dateRangeSorter(a, b) {
if (a[0] < b[0]) return -1;
else if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
else if (a[1] > b[1]) return 1;
return 0;
}
Now we're good to go on the calculation, here is a code snippet that will log the output at the end.
// data
const output = [];
const oneDayInMs = 24 * 60 * 60 * 1000;
const mainDateRange = ['01-01-2020', '14-06-2020'];
const selectedRanges = [
['03-01-2020','04-01-2020'],
['03-01-2020','05-01-2020'],
['11-01-2020','13-01-2020'],
['01-02-2020','20-02-2020'],
['15-03-2020','18-03-2020'],
['06-01-2020','06-01-2020'],
['03-01-2020','04-01-2020']
];
// helpers
function stringToDate(stringDate) {
const parts = stringDate.split('-').map((p) => parseInt(p));
parts[1] -= 1;
return new Date(...parts.reverse());
}
function dateToString(date) {
return `${('0' + date.getDate()).slice(-2)}-${('0' + (date.getMonth() + 1)).slice(-2)}-${date.getFullYear()}`;
}
function dateRangeSorter(a, b) {
if (a[0] < b[0]) return -1;
else if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
else if (a[1] > b[1]) return 1;
return 0;
}
// transform into date and sort
const mainDateRangeAsDates = mainDateRange.map(stringToDate);
const selectedRangesAsDates = selectedRanges.map((range) => (range.map(stringToDate)))
.sort(dateRangeSorter);
// start at the beginning of the main date range
let movingDate = mainDateRangeAsDates[0];
// loop through the selected ranges
selectedRangesAsDates.forEach(([startDate, endDate]) => {
// if there's a gap, add it to the output
if (movingDate < startDate) {
output.push([
dateToString(movingDate),
dateToString(new Date(startDate.getTime() - oneDayInMs))
]);
}
// move the cursor date to one day after the end of current rage
movingDate = new Date(endDate.getTime() + oneDayInMs);
});
// if there is a gap at the end, add it as well
if (movingDate < mainDateRangeAsDates[1]) {
output.push([
dateToString(movingDate),
dateToString(mainDateRangeAsDates[1])
]);
}
console.log(output);
Used a similar approach to this: How to make sure every number of a bigger range is within some smaller ranges?
Convert all strings to Dates. Sorts by minimum of range.
Moves minimum position forward, until it finds a gap, and pushes to res array.
Pushes range from last minimum to maximum if it exists
mainDateRange = ['01-01-2020', '14-06-2020'];
selectedRanges = [
['03-01-2020', '04-01-2020'],
['03-01-2020', '05-01-2020'], //overlapping dates
['11-01-2020', '13-01-2020'],
['01-02-2020', '20-02-2020'],
['15-03-2020', '18-03-2020'],
['06-01-2020', '06-01-2020'], //date ranges will not be ordered
['03-01-2020', '04-01-2020']
]; //dates that the member has work assigned
function gapFinder(mainDateRange, selectedRanges) {
const dateToInt = a => new Date(a.split('-').reverse().join('-'))
const intToDate = a => new Date(a).toISOString().slice(0, 10).split('-').reverse().join('-')
// convert to numbers
selectedRanges = selectedRanges.map(r => r.map(dateToInt))
// presort ranges
selectedRanges.sort(([a, ], [b, ]) => a - b)
let [min, max] = mainDateRange.map(dateToInt)
const res = []
for (const [x, y] of selectedRanges) {
if (min > max) break
if (min < x)
res.push([min, x.setDate(x.getDate() - 1)])
min = Math.max(min, y.setDate(y.getDate() + 1))
}
if (min <= max) res.push([min, max])
return res.map(r => r.map(intToDate))
}
console.log(JSON.stringify(gapFinder(mainDateRange,selectedRanges)))
selectedRanges.push(['11-06-2020', '13-06-2020'])
console.log(JSON.stringify(gapFinder(mainDateRange,selectedRanges)))

How can we get the number of all possible non-negative integers similar to a given non-negative integer by re-arranging it using javascript

Given a non-negative number say 1213, it should return 12 because there are 12 possible integers similar to 1213 i.e., 1123,1132,1213,1231,1312,1321,2113,2131,2311,312,3121 and 3211. Same with 10, it should return 1 and 12 should return 2 and if the number is 120 it should return 4 as combinations are 120,102,210,201.
You can use this formula to get the total number of unique permutations excluding permutations with leading zero.
Lets define some symbols:
n = Total Number of digits
z = Number of zeros
r1, r2, ..., rn = repetition count of digits with count > 1
fact(p) = factorial of number of p
Total permutations = (n - z) * fact(n - 1) / fact(r1) * fact(r2) * .... * fact(rn)
For example, for 1213,
n = 4, z = 0, r1 (digit 1) = 2
permutations = (4 - 0) * fact(4 - 1) / fact(2) = 4 * 6 / 2 = 12
You can easily convert this to program.
function factorial(n) {
if (n <=1)
return 1;
return n * factorial(n-1);
}
function getPermutations(number) {
var n = number.toString().split('').length;
var r = {};
number.toString().split('').forEach(function(digit){
r[digit] = r[digit] || 0;
r[digit] += 1;
});
var z = number.toString().split('').reduce(function(count, digit) {
return (digit === '0') ? count + 1 : count;
}, 0);
var denominator = Object.keys(r).map(function (key) { return r[key]; }).reduce(function(result, curr) {
return result * factorial(curr);
}, 1);
//console.log(n, r, z);
return (n - z) * factorial(n - 1) / denominator;
}
var result = getPermutations(1216);
console.log(result);
Note : This is basic implementation and would not be the most optimum. Also, factorial calculation involves large numbers and would probably fail for large inputs.
You are looking for an anagram algorithm :
This script find every anagram of a string then delete every number starting with zero :
var allAnagrams = function(arr) {
var anagrams = {};
arr.forEach(function(str) {
var recurse = function(ana, str) {
if (str === '')
anagrams[ana] = 1;
for (var i = 0; i < str.length; i++)
recurse(ana + str[i], str.slice(0, i) + str.slice(i + 1));
};
recurse('', str);
});
return Object.keys(anagrams);
}
var arr = ['120']; //declare your number
var anag = allAnagrams(arr); //send it to the function
for (var i in anag) { //delete leading 0
if((anag[i].charAt(0)) === '0' ) {
anag.splice(i);
}
}
console.log(anag); //print array
console.log(anag.length); // print length
Here the output will be :
["102", "120", "201", "210"]
4

Check if a string is sorted in javascript

please i want to check if this string is sorted?
var myBucket = "1D2D1W2W1M2M3M4M5M6M9M1Y18M2Y30M3Y4Y5Y6Y8Y10Y15Y20Y25Y30Y1D2D1W2W1M2M3M4M5M6M9M1Y18M2Y30M3Y4Y5Y6Y8Y10Y15Y20Y25Y30Y";
1D=One Day 2D=2 Day ...
1W=1 Week
1M=1 Months 18M=18 Months
1Y=1 years
like 1D<2D<1W<3W<1M<10M<1Y<18M<2Y ...
How can i check this?
Thank you in advance.
I suggest to match a number and the length indicator. Then loop over with Array#every and split the part into number and length indicator. With a hash table for the length, you could calculate the length and test it with the last value before.
If greater, then proceed, else leave the loop and get false.
If the loop iterates over all elements, and the callback returns true, then it return true.
var myBucket = '1D2D1W2W1M2M3M4M5M6M9M1Y18M2Y30M3Y4Y5Y6Y8Y10Y15Y20Y25Y30Y1D2D1W2W1M2M3M4M5M6M9M1Y18M2Y30M3Y4Y5Y6Y8Y10Y15Y20Y25Y30Y',
values = { D: 1, W: 7, M: 30, Y: 365 },
result = myBucket.match(/\d+[DWMY]/g).every(function (a, i) {
var p = a.split(/(?=[DWMY])/),
value = p[0] * (values[p[1]] || 0);
if (value > this.last) {
this.last = value;
return true;
}
}, { last: -Infinity });
console.log(result);

How to reduce consecutive integers in an array to hyphenated range expressions?

In JavaScript, how can I convert a sequence of numbers in an array to a range of numbers? In other words, I want to express consecutive occurring integers (no gaps) as hyphenated ranges.
[2,3,4,5,10,18,19,20] would become [2-5,10,18-20]
[1,6,7,9,10,12] would become [1,6-7,9-10,12]
[3,5,99] would remain [3,5,99]
[5,6,7,8,9,10,11] would become [5-11]
Here is an algorithm that I made some time ago, originally written for C#, now I ported it to JavaScript:
function getRanges(array) {
var ranges = [], rstart, rend;
for (var i = 0; i < array.length; i++) {
rstart = array[i];
rend = rstart;
while (array[i + 1] - array[i] == 1) {
rend = array[i + 1]; // increment the index if the numbers sequential
i++;
}
ranges.push(rstart == rend ? rstart+'' : rstart + '-' + rend);
}
return ranges;
}
getRanges([2,3,4,5,10,18,19,20]);
// returns ["2-5", "10", "18-20"]
getRanges([1,2,3,5,7,9,10,11,12,14 ]);
// returns ["1-3", "5", "7", "9-12", "14"]
getRanges([1,2,3,4,5,6,7,8,9,10])
// returns ["1-10"]
Just having fun with solution from CMS :
function getRanges (array) {
for (var ranges = [], rend, i = 0; i < array.length;) {
ranges.push ((rend = array[i]) + ((function (rstart) {
while (++rend === array[++i]);
return --rend === rstart;
})(rend) ? '' : '-' + rend));
}
return ranges;
}
Very nice question: here's my attempt:
function ranges(numbers){
var sorted = numbers.sort(function(a,b){return a-b;});
var first = sorted.shift();
return sorted.reduce(function(ranges, num){
if(num - ranges[0][1] <= 1){
ranges[0][1] = num;
} else {
ranges.unshift([num,num]);
}
return ranges;
},[[first,first]]).map(function(ranges){
return ranges[0] === ranges[1] ?
ranges[0].toString() : ranges.join('-');
}).reverse();
}
Demo on JSFiddler
I needed TypeScript code today to solve this very problem -- many years after the OP -- and decided to try a version written in a style more functional than the other answers here. Of course, only the parameter and return type annotations distinguish this code from standard ES6 JavaScript.
function toRanges(values: number[],
separator = '\u2013'): string[] {
return values
.slice()
.sort((p, q) => p - q)
.reduce((acc, cur, idx, src) => {
if ((idx > 0) && ((cur - src[idx - 1]) === 1))
acc[acc.length - 1][1] = cur;
else acc.push([cur]);
return acc;
}, [])
.map(range => range.join(separator));
}
Note that slice is necessary because sort sorts in place and we can't change the original array.
Here's my take on this...
function getRanges(input) {
//setup the return value
var ret = [], ary, first, last;
//copy and sort
var ary = input.concat([]);
ary.sort(function(a,b){
return Number(a) - Number(b);
});
//iterate through the array
for (var i=0; i<ary.length; i++) {
//set the first and last value, to the current iteration
first = last = ary[i];
//while within the range, increment
while (ary[i+1] == last+1) {
last++;
i++;
}
//push the current set into the return value
ret.push(first == last ? first : first + "-" + last);
}
//return the response array.
return ret;
}
Using ES6, a solution is:
function display ( vector ) { // assume vector sorted in increasing order
// display e.g.vector [ 2,4,5,6,9,11,12,13,15 ] as "2;4-6;9;11-13;15"
const l = vector.length - 1; // last valid index of vector array
// map [ 2,4,5,6,9,11,12,13,15 ] into array of strings (quote ommitted)
// --> [ "2;", "4-", "-", "6;", "9;", "11-", "-", "13;", "15;" ]
vector = vector.map ( ( n, i, v ) => // n is current number at index i of vector v
i < l && v [ i + 1 ] - n === 1 ? // next number is adjacent ?
`${ i > 0 && n - v [ i - 1 ] === 1 ? "" : n }-` :
`${ n };`
);
return vector.join ( "" ). // concatenate all strings in vector array
replace ( /-+/g, "-" ). // replace multiple dashes by single dash
slice ( 0, -1 ); // remove trailing ;
}
If you want to add extra spaces for readability, just add extra calls to string.prototype.replace().
If the input vector is not sorted, you can add the following line right after the opening brace of the display() function:
vector.sort ( ( a, b ) => a - b ); // sort vector in place, in increasing order.
Note that this could be improved to avoid testing twice for integer adjacentness (adjacenthood? I'm not a native English speaker;-).
And of course, if you don't want a single string as output, split it with ";".
Rough outline of the process is as follows:
Create an empty array called ranges
For each value in sorted input array
If ranges is empty then insert the item {min: value, max: value}
Else if max of last item in ranges and the current value are consecutive then set max of last item in ranges = value
Else insert the item {min: value, max: value}
Format the ranges array as desired e.g. by combining min and max if same
The following code uses Array.reduce and simplifies the logic by combining step 2.1 and 2.3.
function arrayToRange(array) {
return array
.slice()
.sort(function(a, b) {
return a - b;
})
.reduce(function(ranges, value) {
var lastIndex = ranges.length - 1;
if (lastIndex === -1 || ranges[lastIndex].max !== value - 1) {
ranges.push({ min: value, max: value });
} else {
ranges[lastIndex].max = value;
}
return ranges;
}, [])
.map(function(range) {
return range.min !== range.max ? range.min + "-" + range.max : range.min.toString();
});
}
console.log(arrayToRange([2, 3, 4, 5, 10, 18, 19, 20]));
If you simply want a string that represents a range, then you'd find the mid-point of your sequence, and that becomes your middle value (10 in your example). You'd then grab the first item in the sequence, and the item that immediately preceded your mid-point, and build your first-sequence representation. You'd follow the same procedure to get your last item, and the item that immediately follows your mid-point, and build your last-sequence representation.
// Provide initial sequence
var sequence = [1,2,3,4,5,6,7,8,9,10];
// Find midpoint
var midpoint = Math.ceil(sequence.length/2);
// Build first sequence from midpoint
var firstSequence = sequence[0] + "-" + sequence[midpoint-2];
// Build second sequence from midpoint
var lastSequence = sequence[midpoint] + "-" + sequence[sequence.length-1];
// Place all new in array
var newArray = [firstSequence,midpoint,lastSequence];
alert(newArray.join(",")); // 1-4,5,6-10
Demo Online: http://jsbin.com/uvahi/edit
; For all cells of the array
;if current cell = prev cell + 1 -> range continues
;if current cell != prev cell + 1 -> range ended
int[] x = [2,3,4,5,10,18,19,20]
string output = '['+x[0]
bool range = false; --current range
for (int i = 1; i > x[].length; i++) {
if (x[i+1] = [x]+1) {
range = true;
} else { //not sequential
if range = true
output = output || '-'
else
output = output || ','
output.append(x[i]','||x[i+1])
range = false;
}
}
Something like that.
An adaptation of CMS's javascript solution for Cold Fusion
It does sort the list first so that 1,3,2,4,5,8,9,10 (or similar) properly converts to 1-5,8-10.
<cfscript>
function getRanges(nArr) {
arguments.nArr = listToArray(listSort(arguments.nArr,"numeric"));
var ranges = [];
var rstart = "";
var rend = "";
for (local.i = 1; i <= ArrayLen(arguments.nArr); i++) {
rstart = arguments.nArr[i];
rend = rstart;
while (i < ArrayLen(arguments.nArr) and (val(arguments.nArr[i + 1]) - val(arguments.nArr[i])) == 1) {
rend = val(arguments.nArr[i + 1]); // increment the index if the numbers sequential
i++;
}
ArrayAppend(ranges,rstart == rend ? rstart : rstart & '-' & rend);
}
return arraytolist(ranges);
}
</cfscript>
Tiny ES6 module for you guys. It accepts a function to determine when we must break the sequence (breakDetectorFunc param - default is the simple thing for integer sequence input).
NOTICE: since input is abstract - there's no auto-sorting before processing, so if your sequence isn't sorted - do it prior to calling this module
function defaultIntDetector(a, b){
return Math.abs(b - a) > 1;
}
/**
* #param {Array} valuesArray
* #param {Boolean} [allArraysResult=false] if true - [1,2,3,7] will return [[1,3], [7,7]]. Otherwise [[1.3], 7]
* #param {SequenceToIntervalsBreakDetector} [breakDetectorFunc] must return true if value1 and value2 can't be in one sequence (if we need a gap here)
* #return {Array}
*/
const sequenceToIntervals = function (valuesArray, allArraysResult, breakDetectorFunc) {
if (!breakDetectorFunc){
breakDetectorFunc = defaultIntDetector;
}
if (typeof(allArraysResult) === 'undefined'){
allArraysResult = false;
}
const intervals = [];
let from = 0, to;
if (valuesArray instanceof Array) {
const cnt = valuesArray.length;
for (let i = 0; i < cnt; i++) {
to = i;
if (i < cnt - 1) { // i is not last (to compare to next)
if (breakDetectorFunc(valuesArray[i], valuesArray[i + 1])) {
// break
appendLastResult();
}
}
}
appendLastResult();
} else {
throw new Error("input is not an Array");
}
function appendLastResult(){
if (isFinite(from) && isFinite(to)) {
const vFrom = valuesArray[from];
const vTo = valuesArray[to];
if (from === to) {
intervals.push(
allArraysResult
? [vFrom, vTo] // same values array item
: vFrom // just a value, no array
);
} else if (Math.abs(from - to) === 1) { // sibling items
if (allArraysResult) {
intervals.push([vFrom, vFrom]);
intervals.push([vTo, vTo]);
} else {
intervals.push(vFrom, vTo);
}
} else {
intervals.push([vFrom, vTo]); // true interval
}
from = to + 1;
}
}
return intervals;
};
module.exports = sequenceToIntervals;
/** #callback SequenceToIntervalsBreakDetector
#param value1
#param value2
#return bool
*/
first argument is the input sequence sorted array, second is a boolean flag controlling the output mode: if true - single item (outside the intervals) will be returned as arrays anyway: [1,7],[9,9],[10,10],[12,20], otherwise single items returned as they appear in the input array
for your sample input
[2,3,4,5,10,18,19,20]
it will return:
sequenceToIntervals([2,3,4,5,10,18,19,20], true) // [[2,5], [10,10], [18,20]]
sequenceToIntervals([2,3,4,5,10,18,19,20], false) // [[2,5], 10, [18,20]]
sequenceToIntervals([2,3,4,5,10,18,19,20]) // [[2,5], 10, [18,20]]
Here's a version in Coffeescript
getRanges = (array) ->
ranges = []
rstart
rend
i = 0
while i < array.length
rstart = array[i]
rend = rstart
while array[i + 1] - array[i] is 1
rend = array[i + 1] # increment the index if the numbers sequential
i = i + 1
if rstart == rend
ranges.push rstart + ''
else
ranges.push rstart + '-' + rend
i = i + 1
return ranges
I've written my own method that's dependent on Lo-Dash, but doesn't just give you back an array of ranges, rather, it just returns an array of range groups.
[1,2,3,4,6,8,10] becomes:
[[1,2,3,4],[6,8,10]]
http://jsfiddle.net/mberkom/ufVey/

Categories