Range extraction: Difference between revisions
Content added Content deleted
Line 2,420: | Line 2,420: | ||
===ES6=== |
===ES6=== |
||
====Idiomatic==== |
|||
<lang JavaScript> |
|||
function toRange(arr) { |
|||
const ranges = []; |
|||
const sorted = [...arr.filter(Number.isInteger)].sort((x,y) => Math.sign(x-y)); |
|||
const sequenceBreak = (x,y) => y - x > 1 ; |
|||
let i = 0; |
|||
while ( i < sorted.length ) { |
|||
let j = i ; |
|||
while ( j < sorted.length - 1 && !sequenceBreak( sorted[j], sorted[j+1] ) ) { |
|||
++j; |
|||
} |
|||
const from = sorted[i]; |
|||
const thru = sorted[j]; |
|||
const rangeLen = 1 + j - i; |
|||
if ( from === thru ) { |
|||
ranges.push( [from] ); |
|||
} else { |
|||
if ( rangeLen > 2 ) { |
|||
ranges.push([from,thru]); |
|||
} else { |
|||
ranges.push([from], [thru]); |
|||
} |
|||
} |
|||
i = j+1; |
|||
} |
|||
return ranges.map( range => range.join('-') ).join(','); |
|||
} |
|||
// ----------------------------------------------------------------------------- |
|||
// Test Case |
|||
// ----------------------------------------------------------------------------- |
|||
const expected = '0-2,4,6-8,11,12,14-25,27-33,35-39'; |
|||
const actual = toRange([ |
|||
0, 1, 2, |
|||
4, |
|||
6, 7, 8, |
|||
11, 12, // should be two singletons |
|||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
|||
27, 28, 29, 30, 31, 32, 33, |
|||
35, 36, 37, 38, 39, |
|||
]); |
|||
console.log(`actual output : '${actual}'.`); |
|||
console.log(`expected output : '${expected}'.`); |
|||
console.log(`Correct? ${ actual === expected ? 'Yes' : 'No'}`); |
|||
</lang> |
|||
{{Out}} |
|||
<pre> |
|||
actual output : '0-2,4,6-8,11,12,14-25,27-33,35-39'. |
|||
expected output : '0-2,4,6-8,11,12,14-25,27-33,35-39'. |
|||
Correct? Yes |
|||
</pre> |
|||
====From Haskell==== |
|||
{{Trans|Haskell}} |
{{Trans|Haskell}} |
||
Defining the range format in terms of a reusable '''splitBy''' function: |
Defining the range format in terms of a reusable '''splitBy''' function: |