Installation
Quick Take
API — rMerge()
The main function rMerge()
is imported like this:
It’s a function which takes two input arguments:
Input argument | Type | Obligatory | Description |
---|---|---|---|
arrOfRanges Type: Array Obligatory: yes | |||
arrOfRanges | Array | yes | Array of zero or more arrays meaning natural number ranges (2 elements each) |
opts Type: Plain object Obligatory: no | |||
opts | Plain object | no | Optional Options Object. See its API below. |
None of the input arguments will be mutated by this program, we have unit tests to prove that.
The Optional Options Object has the following shape:
Key | Type | Default | Description |
---|---|---|---|
mergeType Type: number Default: 1 | |||
mergeType | number | 1 | The type of merge. See below for explanation. |
progressFn Type: null or Boolean false or function Default: null | |||
progressFn | null or Boolean false or function | null | If you supply a function here, it will be called, and an argument will be given to it, a natural number, which means percentage complete at that moment. Values will range from 1 to 99 , and finally, the main function will return the result’s plain object. |
joinRangesThatTouchEdges Type: boolean Default: true | |||
joinRangesThatTouchEdges | boolean | true | By default, if two ranges “touch”, [[1, 2], [2, 3]] they are joined. Set this option to false to stop that. Handy when reporting separate issues. |
Here are all defaults in one place for copying:
Function will return merged ranges — a null
(theoretically possible) or array of one or more range arrays:
API — defaults
You can import defaults
:
It's a plain object:
The main function calculates the options to be used by merging the options you passed with these defaults.
API — version
You can import version
:
opts.progressFn
Consider this example (notice an arrow function in the second input argument):
console.log(
rMerge(
[
[1, 5],
[11, 15],
[6, 10],
[16, 20],
[10, 30],
],
{
progressFn: (perc) => {
console.log(`done: ${perc}`);
},
}
)
);
//
// done: 0
// done: 1
// done: 2
// done: 3
// done: 4
// done: 4
// done: 5
// done: 21
// done: 40
// done: 60
// done: 79
// done: 99
// [[1, 5], [6, 30]]
Imagine, instead of console.log
, this function could sit in a worker and report its progress, then, finally, ping the last value — result.
Whatever function you give in opts.progressFn
, it will be called with percentage done so far. Grab that argument (perc
in the example above) and do whatever you want with it in your function.
opts.mergeType
When merging, ranges are sorted first. Then, pairs starting from the end of the sorted array are merged. Last two becomes one, last two becomes one and so on.
The challenge is, what to do with values to add, third range array’s element.
For example,
const range1 = [1, 2, "a"];
const range2 = [1, 2, "b"];
The above ranges are “saying”: replace characters in a string from index 1
to 2
with "a"
, replace characters in string from index 1
to 2
with "b"
.
Do we end up with "ab"
or "b"
or something else?
opts.mergeType
let’s you customise this behaviour:
- In default mode, opts.mergeType ===
1
, clashing “to insert” values will always be concatenated ("ab"
in example above) - In mode opts.mergeType ===
2
, if “to insert” values clash and starting indexes are the same — the latter value overrides the former ("b"
in example above).
In all other aspects, opts.mergeType
modes 1
and 2
are the same.
Example
Imagine a messed up piece of code: <div>&nbbsp;</div>
. Let’s say our imaginary cleaning program detected two issues with it:
- Unencoded ampersand at position
5
- Malformed
whereb
is duplicated
Range-wise, it could look like this:
[
{
name: "bad-character-unencoded-ampersand",
position: [[5, 6, "&"]],
},
{
name: "malformed ",
position: [[5, 12, " "]],
},
];
Notice we have two ranges’ “insert” values clashing, [5, 6]
and [5, 12]
, but we want latter to discard the former. That’s where opts.mergeType
setting 2
come in.
Mode 2
is the same to 1
except clashing “insert” values are resolved by deleting value on the left and keeping one on the right, in the order of sorted ranges array.
For example,
import { rMerge } from "ranges-merge";
const res1 = rMerge(
[
[3, 4, "aaa"],
[3, 12, "zzz"],
],
{ mergeType: 1 }
);
console.log(res1);
// => [[3, 12, "aaazzz"]]
const res2 = rMerge(
[
[3, 4, "aaa"],
[3, 12, "zzz"],
],
{ mergeType: 2 }
);
console.log(res2);
// => [[3, 12, "zzz"]]
In the example above, notice how ranges got sorted. The sorting algorithm first sorted by first element (3
which was the same on both) then on a second (4
vs 12
). The range [3, 12, "zzz"]
came second, its third element, “what to insert”, "zzz"
clashed with first one’s "aaa"
, wiping it.