Skip to content

Commit

Permalink
Add individualThreshold option to stringify()
Browse files Browse the repository at this point in the history
  • Loading branch information
smikitky committed Mar 9, 2023
1 parent 24eaaf4 commit e06d0ee
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 14 deletions.
19 changes: 17 additions & 2 deletions api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,19 +424,32 @@ init([[2, 5], [8, 10]]); // [[2, 5], [8, 9]]
## function: `stringify`

```ts
stringify(data: MultiIntegerRange): string
stringify(
data: MultiIntegerRange,
options: StringifyOptions = {}
): string
```

| Param | Description |
|-|-|
| `data` | The MultiIntegerRange to stringify. |
| `options` | Options for the stringification. |
| Returns | The string representation of the given data. |

Returns the string respresentation of the given MultiIntegerRange.

- `options.individualThreshold` (number): If set, small ranges with a length
smaller than or equal to this will be output as individual integers.
Defaults to `1`, which means only ranges with a length of 1 will be
output as a single integer.

### Example

```ts
stringify([[2, 3], [5, 5], [7, 9]]); // '2-3,5,7-9'
stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 0 }); // '2-3,5-5,7-9'
stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 2 }); // '2,3,5,7-9'
stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 3 }); // '2,3,5,7,8,9'
stringify([[3, 5], [7, Infinity]]); // '3-5,7-'
```

Expand Down Expand Up @@ -477,11 +490,13 @@ iterate(
| Param | Description |
|-|-|
| `data` | The normalized MultiIntegerRange to iterate over. |
| `options` | Pass `{ descending: true }` to iterate in descending order. |
| `options` | Options for the iteration. |
| Returns | An Iterable object. |

Returns an Iterable with which you can use `for-of` or the spread syntax.

- `options.descending` (boolean): If set to true, the iterator will iterate in descending order.

### Example

```ts
Expand Down
3 changes: 2 additions & 1 deletion scripts/docgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const fs = require('fs/promises');
const parseDocComment = docComment => {
const lines = docComment
.split('\n')
.map(s => s.replace(/^\s*(\/\*\*|\*)?\s*/g, ''));
.map(s => s.replace(/^\s*(\/\*\*|\*)?\s?/g, ''));
const tags = {};
let currentTag = 'summary';
let currentTagContent = '';
Expand Down Expand Up @@ -77,6 +77,7 @@ const buildMarkdown = parsed => {
''
];

// TOC
parsed
.filter(item => item.type === 'function')
.forEach(item => {
Expand Down
9 changes: 9 additions & 0 deletions src/fp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,15 @@ test('stringify', () => {
t('-10');
t('10-');
t('');

const r = mr.parse('2-3,5,7-9');
const t2 = (individualThreshold: number, expected: string) =>
expect(mr.stringify(r, { individualThreshold })).toBe(expected);
t2(0, '2-3,5-5,7-9');
t2(1, '2-3,5,7-9');
t2(2, '2,3,5,7-9');
t2(3, '2,3,5,7,8,9');
t2(4, '2,3,5,7,8,9');
});

test('flatten', () => {
Expand Down
53 changes: 42 additions & 11 deletions src/fp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ const findOverlap = (
* @param a - The first value.
* @param b - The second value.
* @returns A new MultiIntegerRange containing all integers that belong to
* **either `a` or `b` (or both)**.
* **either `a` or `b` (or both)**.
* @example
* append([[1, 5]], [[3, 8], [10, 15]]); // [[1, 8], [10, 15]]
* append([[5, 9]], [[-Infinity, 2]]); // [[-Infinity, 2], [5, 9]]
Expand All @@ -264,7 +264,7 @@ export const append = (a: MIR, b: MIR): MIR => {
* @param a - The value to be subtracted.
* @param b - The value to subtract.
* @returns A new MultiIntegerRange containing all integers that belong to
* **`a` but not `b`**.
* **`a` but not `b`**.
* @example
* subtract([[1, 7]], [[2, 4]]); // [[1, 1], [5, 7]]
* subtract([[-Infinity, Infinity]], [[2, 4]]); // [[-Infinity, 1], [5, Infinity]]
Expand Down Expand Up @@ -292,7 +292,7 @@ export const subtract = (a: MIR, b: MIR): MIR => {
* @param a - The first value.
* @param b - The second value.
* @returns A new MultiIntegerRange containing all integers
* that belong to **both `a` and `b`**.
* that belong to **both `a` and `b`**.
* @example
* intersect([[2, 5]], [[4, 9]]); // [[4, 5]]
* intersect([[5, 10]], [[-Infinity, Infinity]]); // [[5, 10]]
Expand Down Expand Up @@ -429,7 +429,7 @@ export const max = (data: MIR): number | undefined => {
* @param data - The value.
* @param index - The 0-based index of the integer to return. Can be negative.
* @returns The integer at the specified index.
* Returns `undefined` if the index is out of bounds.
* Returns `undefined` if the index is out of bounds.
* @example
* at([[2, 4], [8, 10]], 4); // 9
* at([[2, 4], [8, 10]], 6); // undefined
Expand Down Expand Up @@ -464,7 +464,7 @@ export const at = (data: MIR, index: number): number | undefined => {
* Returns all but the minimum integer.
* @param data - The value.
* @returns A new MultiIntegerRange which is almost the same as `data` but with
* its minimum integer removed.
* its minimum integer removed.
* @example
* tail([[2, 5], [8, 10]]); // [[3, 5], [8, 10]]
*/
Expand All @@ -482,7 +482,7 @@ export const tail = (data: MIR): MIR => {
* Returns all but the maximum integer.
* @param data - The value.
* @returns A new MultiIntegerRange which is almost the same as `data` but with
* its maximum integer removed.
* its maximum integer removed.
* @example
* init([[2, 5], [8, 10]]); // [[2, 5], [8, 9]]
*/
Expand All @@ -496,14 +496,36 @@ export const init = (data: MIR): MIR => {
return subtract(data, [[m, m]]);
};

/**
* Options for the `stringify()` function.
*/
export interface StringifyOptions {
individualThreshold?: number;
}

/**
* Returns the string respresentation of the given MultiIntegerRange.
*
* - `options.individualThreshold` (number): If set, small ranges with a length
* smaller than or equal to this will be output as individual integers.
* Defaults to `1`, which means only ranges with a length of 1 will be
* output as a single integer.
*
* @param data - The MultiIntegerRange to stringify.
* @param options - Options for the stringification.
* @returns The string representation of the given data.
* @example
* stringify([[2, 3], [5, 5], [7, 9]]); // '2-3,5,7-9'
* stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 0 }); // '2-3,5-5,7-9'
* stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 2 }); // '2,3,5,7-9'
* stringify([[2, 3], [5, 5], [7, 9]], { individualThreshold: 3 }); // '2,3,5,7,8,9'
* stringify([[3, 5], [7, Infinity]]); // '3-5,7-'
*/
export const stringify = (data: MIR): string => {
export const stringify = (
data: MIR,
options: StringifyOptions = {}
): string => {
const { individualThreshold = 1 } = options;
const wrap = (i: number) => (i >= 0 ? String(i) : `(${i})`);
const ranges: string[] = [];
for (let r of data) {
Expand All @@ -515,10 +537,10 @@ export const stringify = (data: MIR): string => {
}
} else if (r[1] === Infinity) {
ranges.push(`${wrap(r[0])}-`);
} else if (r[0] == r[1]) {
ranges.push(wrap(r[0]));
} else {
ranges.push(`${wrap(r[0])}-${wrap(r[1])}`);
if (individualThreshold && r[1] - r[0] + 1 <= individualThreshold) {
for (let i = r[0]; i <= r[1]; i++) ranges.push(wrap(i));
} else ranges.push(`${wrap(r[0])}-${wrap(r[1])}`);
}
}
return ranges.join(',');
Expand Down Expand Up @@ -547,14 +569,23 @@ export const flatten = (data: MIR): number[] => {
return result;
};

/**
* Options for the `iterate()` function.
*/
export interface IterateOptions {
/**
* Whether to iterate in descending order.
*/
readonly descending?: boolean;
}

/**
* Returns an Iterable with which you can use `for-of` or the spread syntax.
*
* - `options.descending` (boolean): If set to true, the iterator will iterate in descending order.
*
* @param data - The normalized MultiIntegerRange to iterate over.
* @param options - Pass `{ descending: true }` to iterate in descending order.
* @param options - Options for the iteration.
* @returns An Iterable object.
* @example
* Array.from(iterate([[1, 3], [7, 9]])); // [1, 2, 3, 7, 8, 9]
Expand Down

0 comments on commit e06d0ee

Please sign in to comment.