@@ -245,7 +245,7 @@ const findOverlap = (
245
245
* @param a - The first value.
246
246
* @param b - The second value.
247
247
* @returns A new MultiIntegerRange containing all integers that belong to
248
- * **either `a` or `b` (or both)**.
248
+ * **either `a` or `b` (or both)**.
249
249
* @example
250
250
* append([[1, 5]], [[3, 8], [10, 15]]); // [[1, 8], [10, 15]]
251
251
* append([[5, 9]], [[-Infinity, 2]]); // [[-Infinity, 2], [5, 9]]
@@ -264,7 +264,7 @@ export const append = (a: MIR, b: MIR): MIR => {
264
264
* @param a - The value to be subtracted.
265
265
* @param b - The value to subtract.
266
266
* @returns A new MultiIntegerRange containing all integers that belong to
267
- * **`a` but not `b`**.
267
+ * **`a` but not `b`**.
268
268
* @example
269
269
* subtract([[1, 7]], [[2, 4]]); // [[1, 1], [5, 7]]
270
270
* subtract([[-Infinity, Infinity]], [[2, 4]]); // [[-Infinity, 1], [5, Infinity]]
@@ -292,7 +292,7 @@ export const subtract = (a: MIR, b: MIR): MIR => {
292
292
* @param a - The first value.
293
293
* @param b - The second value.
294
294
* @returns A new MultiIntegerRange containing all integers
295
- * that belong to **both `a` and `b`**.
295
+ * that belong to **both `a` and `b`**.
296
296
* @example
297
297
* intersect([[2, 5]], [[4, 9]]); // [[4, 5]]
298
298
* intersect([[5, 10]], [[-Infinity, Infinity]]); // [[5, 10]]
@@ -429,7 +429,7 @@ export const max = (data: MIR): number | undefined => {
429
429
* @param data - The value.
430
430
* @param index - The 0-based index of the integer to return. Can be negative.
431
431
* @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.
433
433
* @example
434
434
* at([[2, 4], [8, 10]], 4); // 9
435
435
* at([[2, 4], [8, 10]], 6); // undefined
@@ -464,7 +464,7 @@ export const at = (data: MIR, index: number): number | undefined => {
464
464
* Returns all but the minimum integer.
465
465
* @param data - The value.
466
466
* @returns A new MultiIntegerRange which is almost the same as `data` but with
467
- * its minimum integer removed.
467
+ * its minimum integer removed.
468
468
* @example
469
469
* tail([[2, 5], [8, 10]]); // [[3, 5], [8, 10]]
470
470
*/
@@ -482,7 +482,7 @@ export const tail = (data: MIR): MIR => {
482
482
* Returns all but the maximum integer.
483
483
* @param data - The value.
484
484
* @returns A new MultiIntegerRange which is almost the same as `data` but with
485
- * its maximum integer removed.
485
+ * its maximum integer removed.
486
486
* @example
487
487
* init([[2, 5], [8, 10]]); // [[2, 5], [8, 9]]
488
488
*/
@@ -496,14 +496,36 @@ export const init = (data: MIR): MIR => {
496
496
return subtract ( data , [ [ m , m ] ] ) ;
497
497
} ;
498
498
499
+ /**
500
+ * Options for the `stringify()` function.
501
+ */
502
+ export interface StringifyOptions {
503
+ individualThreshold ?: number ;
504
+ }
505
+
499
506
/**
500
507
* 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
+ *
501
514
* @param data - The MultiIntegerRange to stringify.
515
+ * @param options - Options for the stringification.
502
516
* @returns The string representation of the given data.
503
517
* @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'
504
522
* stringify([[3, 5], [7, Infinity]]); // '3-5,7-'
505
523
*/
506
- export const stringify = ( data : MIR ) : string => {
524
+ export const stringify = (
525
+ data : MIR ,
526
+ options : StringifyOptions = { }
527
+ ) : string => {
528
+ const { individualThreshold = 1 } = options ;
507
529
const wrap = ( i : number ) => ( i >= 0 ? String ( i ) : `(${ i } )` ) ;
508
530
const ranges : string [ ] = [ ] ;
509
531
for ( let r of data ) {
@@ -515,10 +537,10 @@ export const stringify = (data: MIR): string => {
515
537
}
516
538
} else if ( r [ 1 ] === Infinity ) {
517
539
ranges . push ( `${ wrap ( r [ 0 ] ) } -` ) ;
518
- } else if ( r [ 0 ] == r [ 1 ] ) {
519
- ranges . push ( wrap ( r [ 0 ] ) ) ;
520
540
} 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 ] ) } ` ) ;
522
544
}
523
545
}
524
546
return ranges . join ( ',' ) ;
@@ -547,14 +569,23 @@ export const flatten = (data: MIR): number[] => {
547
569
return result ;
548
570
} ;
549
571
572
+ /**
573
+ * Options for the `iterate()` function.
574
+ */
550
575
export interface IterateOptions {
576
+ /**
577
+ * Whether to iterate in descending order.
578
+ */
551
579
readonly descending ?: boolean ;
552
580
}
553
581
554
582
/**
555
583
* 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
+ *
556
587
* @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 .
558
589
* @returns An Iterable object.
559
590
* @example
560
591
* Array.from(iterate([[1, 3], [7, 9]])); // [1, 2, 3, 7, 8, 9]
0 commit comments