@@ -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