@@ -245,7 +245,7 @@ const findOverlap = (
245245 * @param a - The first value.
246246 * @param b - The second value.
247247 * @returns A new MultiIntegerRange containing all integers that belong to
248- * **either `a` or `b` (or both)**.
248+ * **either `a` or `b` (or both)**.
249249 * @example
250250 * append([[1, 5]], [[3, 8], [10, 15]]); // [[1, 8], [10, 15]]
251251 * append([[5, 9]], [[-Infinity, 2]]); // [[-Infinity, 2], [5, 9]]
@@ -264,7 +264,7 @@ export const append = (a: MIR, b: MIR): MIR => {
264264 * @param a - The value to be subtracted.
265265 * @param b - The value to subtract.
266266 * @returns A new MultiIntegerRange containing all integers that belong to
267- * **`a` but not `b`**.
267+ * **`a` but not `b`**.
268268 * @example
269269 * subtract([[1, 7]], [[2, 4]]); // [[1, 1], [5, 7]]
270270 * subtract([[-Infinity, Infinity]], [[2, 4]]); // [[-Infinity, 1], [5, Infinity]]
@@ -292,7 +292,7 @@ export const subtract = (a: MIR, b: MIR): MIR => {
292292 * @param a - The first value.
293293 * @param b - The second value.
294294 * @returns A new MultiIntegerRange containing all integers
295- * that belong to **both `a` and `b`**.
295+ * that belong to **both `a` and `b`**.
296296 * @example
297297 * intersect([[2, 5]], [[4, 9]]); // [[4, 5]]
298298 * intersect([[5, 10]], [[-Infinity, Infinity]]); // [[5, 10]]
@@ -429,7 +429,7 @@ export const max = (data: MIR): number | undefined => {
429429 * @param data - The value.
430430 * @param index - The 0-based index of the integer to return. Can be negative.
431431 * @returns The integer at the specified index.
432- * Returns `undefined` if the index is out of bounds.
432+ * Returns `undefined` if the index is out of bounds.
433433 * @example
434434 * at([[2, 4], [8, 10]], 4); // 9
435435 * at([[2, 4], [8, 10]], 6); // undefined
@@ -464,7 +464,7 @@ export const at = (data: MIR, index: number): number | undefined => {
464464 * Returns all but the minimum integer.
465465 * @param data - The value.
466466 * @returns A new MultiIntegerRange which is almost the same as `data` but with
467- * its minimum integer removed.
467+ * its minimum integer removed.
468468 * @example
469469 * tail([[2, 5], [8, 10]]); // [[3, 5], [8, 10]]
470470 */
@@ -482,7 +482,7 @@ export const tail = (data: MIR): MIR => {
482482 * Returns all but the maximum integer.
483483 * @param data - The value.
484484 * @returns A new MultiIntegerRange which is almost the same as `data` but with
485- * its maximum integer removed.
485+ * its maximum integer removed.
486486 * @example
487487 * init([[2, 5], [8, 10]]); // [[2, 5], [8, 9]]
488488 */
@@ -496,14 +496,36 @@ export const init = (data: MIR): MIR => {
496496 return subtract ( data , [ [ m , m ] ] ) ;
497497} ;
498498
499+ /**
500+ * Options for the `stringify()` function.
501+ */
502+ export interface StringifyOptions {
503+ individualThreshold ?: number ;
504+ }
505+
499506/**
500507 * Returns the string respresentation of the given MultiIntegerRange.
508+ *
509+ * - `options.individualThreshold` (number): If set, small ranges with a length
510+ * smaller than or equal to this will be output as individual integers.
511+ * Defaults to `1`, which means only ranges with a length of 1 will be
512+ * output as a single integer.
513+ *
501514 * @param data - The MultiIntegerRange to stringify.
515+ * @param options - Options for the stringification.
502516 * @returns The string representation of the given data.
503517 * @example
518+ * stringify([[2, 3], [5, 5], [7, 9]]); // '2-3,5,7-9'
519+ * stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 0 }); // '2-3,5-5,7-9'
520+ * stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 2 }); // '2,3,5,7-9'
521+ * stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 3 }); // '2,3,5,7,8,9'
504522 * stringify([[3, 5], [7, Infinity]]); // '3-5,7-'
505523 */
506- export const stringify = ( data : MIR ) : string => {
524+ export const stringify = (
525+ data : MIR ,
526+ options : StringifyOptions = { }
527+ ) : string => {
528+ const { individualThreshold = 1 } = options ;
507529 const wrap = ( i : number ) => ( i >= 0 ? String ( i ) : `(${ i } )` ) ;
508530 const ranges : string [ ] = [ ] ;
509531 for ( let r of data ) {
@@ -515,10 +537,10 @@ export const stringify = (data: MIR): string => {
515537 }
516538 } else if ( r [ 1 ] === Infinity ) {
517539 ranges . push ( `${ wrap ( r [ 0 ] ) } -` ) ;
518- } else if ( r [ 0 ] == r [ 1 ] ) {
519- ranges . push ( wrap ( r [ 0 ] ) ) ;
520540 } else {
521- ranges . push ( `${ wrap ( r [ 0 ] ) } -${ wrap ( r [ 1 ] ) } ` ) ;
541+ if ( individualThreshold && r [ 1 ] - r [ 0 ] + 1 <= individualThreshold ) {
542+ for ( let i = r [ 0 ] ; i <= r [ 1 ] ; i ++ ) ranges . push ( wrap ( i ) ) ;
543+ } else ranges . push ( `${ wrap ( r [ 0 ] ) } -${ wrap ( r [ 1 ] ) } ` ) ;
522544 }
523545 }
524546 return ranges . join ( ',' ) ;
@@ -547,14 +569,23 @@ export const flatten = (data: MIR): number[] => {
547569 return result ;
548570} ;
549571
572+ /**
573+ * Options for the `iterate()` function.
574+ */
550575export interface IterateOptions {
576+ /**
577+ * Whether to iterate in descending order.
578+ */
551579 readonly descending ?: boolean ;
552580}
553581
554582/**
555583 * Returns an Iterable with which you can use `for-of` or the spread syntax.
584+ *
585+ * - `options.descending` (boolean): If set to true, the iterator will iterate in descending order.
586+ *
556587 * @param data - The normalized MultiIntegerRange to iterate over.
557- * @param options - Pass `{ descending: true }` to iterate in descending order .
588+ * @param options - Options for the iteration .
558589 * @returns An Iterable object.
559590 * @example
560591 * Array.from(iterate([[1, 3], [7, 9]])); // [1, 2, 3, 7, 8, 9]
0 commit comments