RangeGroup

A RangeGroup holds a list of contiguous ranges, allowing you to perform efficient set operations on them. Create a new RangeGroup like so:

// Optionally set a default type first
RangeGroup.default_type = IntType

// Supply a preconstructed Range object
new RangeGroup([{start:0, end:5}])
// Arguments to construct ranges
new RangeGroup([[0,5]])

// You can also pass a single Range, rather than a list
new RangeGroup({start:0, end:5})
// Arguments to construct a range
new RangeGroup([0,5])
// However the following would not be allowed, as they're interpreted as a list of Ranges
new RangeGroup([new Date(),5]) // bad!
new RangeGroup([["array","arg"],5]) // bad!

A RangeGroup must be in normalized form before you perform any other operations on it. This means its list of ranges are sorted (RangeGroup#sort) and non-intersecting (RangeGroup#selfUnion). To make it normalized, call RangeGroup#normalize, or pass normalize=true option for your newly constructed RangeGroup. For efficiency, this is not done automatically, as typical inputs are already "pre-normalized". Whenever you modify RangeGroup#ranges manually, you need to make sure you normalize again (if needed) before calling other methods.

Constructor

new RangeGroup(ranges, optionsnullable)

Create a new RangeGroup

Parameters:
NameTypeAttributesDescription
rangesRangeGroup~Definition

Initial set of ranges for this group

optionsRangeGroup~CreateOptions<nullable>

Options for creation

Members

ranges :Array.<Range>

Internal list of ranges

Type:

type :RangeType

Range type to use for this group

(static) default_type :RangeType

Default type to be used if none is provided in the constructor of RangeGroup

Methods

@@iterator()

Iterator interface, allowing use with things like for-of loops or Array.from. To customize how the values are iterated, pass arguments to RangeGroup#iterate instead.

add()

An alias for RangeGroup#union

cardinality()

An alias for RangeGroup#size

clear() → {RangeGroup}

Remove all elements from this group

Returns:

modified this

Type: 
RangeGroup

contains()

An alias for RangeGroup#has

copy() → {RangeGroup}

Make a deep copy of this range group. This calls RangeType.copy internally.

Returns:
Type: 
RangeGroup

delete()

diff(other, optionsnullable) → {RangeGroup|boolean}

Compute the differences between this and another RangeGroup. For diff results, this and other are referred to as a and b respectively. There are three different operations, denoted a, b, and ab. They can be understood as:

  • a: values present in a but not b; set difference "a - b"; deletions from other
  • b: values present in b but not a; set difference "b - a"; insertions into other
  • ab: values present in both a and b; set intersection "a ∩ b"

Filtering by the various diff operations can give you set operations like union, intersection, difference, and symmetric difference (see filter param). This method is used to implement nearly all the other operations on RangeGroup.

The default options will compute set operations. For a more traditional "diff" behavior, use options: {copy:true, track_sources:true, self_union:false}. This gives you the full differences between the two groups, telling you which parts came from a or b. You can reuse this result multiple times to get set operations, simply by filterering for Range#a and/or Range#b. See RangeGroup#filter and its variants, or the filter option of RangeGroup#selfUnion adn its variants.

Parameters:
NameTypeAttributesDescription
otherRangeGroup | RangeGroup~Definition

The group to diff against

optionsRangeGroup~DiffOptions<nullable>

Options to customize the diff behavior

Returns:

Contains the diff result range group, which may equal this if copy was false. If bool was true, a boolean value is instead returned indicating whether that range group would have been non-empty.

Type: 
RangeGroup | boolean

difference(other) → {RangeGroup}

Compute the in-place set difference between this and other: a - b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

modified this

Type: 
RangeGroup

filter(predicate) → {RangeGroup}

Filter the ranges. You might use this to filter by Range#a or Range#b nullity, as returned by RangeGroup#diff

Parameters:
NameTypeDescription
predicateRangeGroup~Filter
Returns:

modified this

Type: 
RangeGroup

has(…args) → {boolean}

Test whether an element is contained in this group. This uses RangeGroup#search internally, returning the has result.

Parameters:
NameTypeAttributesDescription
argsany<repeatable>

arguments are the same as RangeGroup#search

Returns:
Type: 
boolean

hasDifference(other) → {boolean}

Check if this has values not present in other: a - b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:
Type: 
boolean

hasFilter(predicate) → {boolean}

Check if any range matches the filter predicate

Parameters:
NameTypeDescription
predicateRangeGroup~Filter
Returns:
Type: 
boolean

hasIntersection(other) → {boolean}

Check if this intersects with other: a ∩ b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:
Type: 
boolean

hasSelfUnion(filternullable) → {boolean}

Check if any ranges would remain after calling RangeGroup#selfUnion. This is as though the bool option were set to true

Parameters:
NameTypeAttributesDescription
filterRangeGroup~Filter<nullable>

optional filter param, which is the same as the filter that can be passed to RangeGroup#selfUnion

Returns:
Type: 
boolean

hasSymmetricDifference(other) → {boolean}

Check if this has values not present in other: a - b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:
Type: 
boolean

hasUnion(other) → {boolean}

Check if a union of this and other would be non-empty: a ∪ b.

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:
Type: 
boolean

intersect(other) → {RangeGroup}

Compute the in-place set intersection between this and other: a ∩ b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

modified this

Type: 
RangeGroup

isEmpty() → {boolean}

Check if this range group is empty, meaning there are no elements: a = ∅

Returns:

true if empty

Type: 
boolean

isEqual(other) → {boolean}

Check if this and other range groups are equal, meaning they have identical elements: a = b. This uses RangeGroup#hasSymmetricDifference internally, returning its negated value

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

true if equal

Type: 
boolean

isProperSubset(other) → {boolean}

Check whether this is a proper/strict subset of other, meaning all of its elements are in other, but does not have all the elements of other: a ⊂ b. This uses two calls to RangeGroup#hasDifference internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

true if a proper/strict subset

Type: 
boolean

isProperSuperset(other) → {boolean}

Check whether this is a proper/strict superset of other, meaning all other elements are also in this: a ⊃ b. This is equivalent to other.isProperSubset(this)

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

true if a proper/strict superset

Type: 
boolean

isStrictSubset()

isStrictSuperset()

isSubset(other) → {boolean}

Check whether this is a subset of other, meaning all of its elements are also in other: a ⊆ b. This uses RangeGroup#hasDifference internally, returning its negated value

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

true if a subset

Type: 
boolean

isSuperset(other) → {boolean}

Check whether this is a superset of other, meaning all other elements are also in this: a ⊇ b. This is equivalent to other.isSubset(this)

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

true if a superset

Type: 
boolean

(generator) iterate(reversenullable, …args) → {any}

Generator for values within the range group. This calls RangeType.iterate internally.

Parameters:
NameTypeAttributesDefaultDescription
reverseboolean<nullable>
false

iterate ranges forward or backward; forward indicates the first value will give a negative comparison against any subsequent values

argsany<repeatable>

arguments to forward to the RangeType's iterator

Yields:

values from the range

Type: 
any

normalize() → {RangeGroup}

Puts the range group into a normalized form, where ranges are sorted and self intersections have been removed. This calls RangeGroup#sort and RangeGroup#selfUnion

Returns:

modified this

Type: 
RangeGroup

Find the position in RangeGroup#ranges where element could be inserted to maintain a sorted array. If the element belongs to a range already, then the index to that range would be returned, with has flag set. In other words, the index is the lower bound: the first position that does not come before element.

The search output provides useful comparison information that was used to find the location. For a simple boolean output, you may wish to use RangeGroup#has instead.

Parameters:
NameTypeAttributesDescription
elementany

the element to search for

optionsRangeGroup~SearchOptions<nullable>

customizes the options

selfUnion(options) → {RangeGroup|boolean}

Union of individual ranges within this range group (e.g. remove self-intersections). This will remove empty ranges, where the start is after (and not equal) the end.

Parameters:
NameTypeDescription
optionsRangeGroup~SelfUnionOptions

alters the self union behavior to accomodate a few different, common operations

Returns:

By default, modified this. If copy flag was set, it will return a modified copy instead. If bool flag was set, it will return true/false, whether the result would have been non-empty

Type: 
RangeGroup | boolean

size() → {number}

Get the total number of elements held by this group. This dynamically sums up the size of each range in the group, so it is not a constant-time operation. This calls RangeType.size internally.

If you wish to see how many contiguous ranges there are, get the length of RangeGroup#ranges instead.

Returns:
Type: 
number

sort() → {RangeGroup}

Performs an in-place sort of ranges in the group. Ranges are ordered by their start

Returns:

modified this

Type: 
RangeGroup

subtract()

symmetricDifference(other) → {RangeGroup}

Compute the in-place set symmetric difference between this and other: a Δ b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

modified this

Type: 
RangeGroup

toCleared() → {RangeGroup}

Same as RangeGroup#clear, but returns a copy that is cleared. This is functionally equivalent to creating a new range group with the same type

Returns:
Type: 
RangeGroup

toDifferenced(other) → {RangeGroup}

Same as RangeGroup#difference, but returning a copy instead of modifying the range group in-place

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

new group containing the difference

Type: 
RangeGroup

toFiltered(predicate) → {RangeGroup}

Same as RangeGroup#filter, but returns a copy instead

Parameters:
NameTypeDescription
predicateRangeGroup~Filter
Returns:

a filtered copy

Type: 
RangeGroup

toIntersected(other) → {RangeGroup}

Same as RangeGroup#intersect, but returning a copy instead of modifying the range group in-place

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

new group containing the intersection

Type: 
RangeGroup

toSelfUnioned(filternullable)

Same as RangeGroup#selfUnion, but returns a copy instead. This is as though the copy option were set to true

Parameters:
NameTypeAttributesDescription
filterRangeGroup~Filter<nullable>

optional filter param, which is the same as the filter that can be passed to RangeGroup#selfUnion

toSymmetricDifferenced(other) → {RangeGroup}

Same as RangeGroup#symmetricDifference, but returning a copy instead of modifying the range group in-place

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

new group containing the symmetric difference

Type: 
RangeGroup

toUnioned(other) → {RangeGroup}

Same as RangeGroup#union, but returning a copy instead of modifying the range group in-place

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

new group containing the union

Type: 
RangeGroup

union(other) → {RangeGroup}

Compute the in-place set union between this and other: a ∪ b. This uses RangeGroup#diff internally

Parameters:
NameTypeDescription
otherRangeGroup | RangeGroup~Definition
Returns:

modified this

Type: 
RangeGroup

Type Definitions

CreateOptions

Options to pass to the constructor of RangeGroup

Type:
  • object
Properties
NameTypeAttributesDefaultDescription
typeRangeType<optional>
<nullable>
null

Range type to be used with this group; if null, it uses RangeGroup.default_type

normalizeboolean<optional>
false

whether to call RangeGroup#normalize after construction

Definition

Arguments defining a RangeGroup. A falsey value initializes an empty RangeGroup. Otherwise, this should be an array containing ranges for the group; each range can be a preconstructed Range or an array of arguments to construct one. Any Range will be reused, while the containing array is copied.

Caution: Since a Range will be reused, auto-normalizing types like IntNormType are going to assume the ranges are already normalized to be inclusive. You can pass arguments to construct a new Range to construct an auto-normalized range instead.

For convenience, you can also pass just a single preconstructed range. You can pass a single array of arguments to construct a range as well, but only if the first argument is not an object (as identified by typeof).

Type:
  • any

DiffOptions

Options for calculating diff between two range groups. For use with RangeGroup#diff

Type:
  • object
Properties
NameTypeAttributesDefaultDescription
filterobject.<string, boolean> | number | false<optional>
false

Specifies what diff operations you want to include in the results. Indicate which parts, a, b, or ab to include using an object of boolean flags, e.g. {ab:true, b:true}. Alternatively, specify a bit set of flags, where bits 0 (LSb), 1, and 2 correspond to a, b, and ab respectively; e.g. 0b111.

Setting this to a falsey value (the default) will return all results, e.g. {a:true, b:true, ab:true} or 0b111;

boolboolean<optional>
false

Just return true/false whether or not the filtered output would be non-empty; when true, all remaining options are ignored

copyboolean<optional>
true

If true, returns the diff results separately, rather than modifying this in-place

track_sourcesboolean<optional>
false

In the diff output, track where the range came from with the keys Range#a and Range#b, with values equaling the index into this/other respectively that the range came from. A value of null indicates the range was not present in that source. Filtering by nullity can give you the various set operations like union or intersection.

self_unionboolean<optional>
true

Merges adjacent ranges, in the same manner as RangeGroup#selfUnion, but using an inline calculation. Use this if you don't care about tracking the specific diff sources/operations, and just want to get the result of the set operationon output. The track_sources option is disabled if this is true.

Filter(range) → {boolean}

Used for a few different methods to filter RangeGroup#ranges

Parameters:
NameTypeDescription
rangeRange

the range to check whether it should be included

Returns:

whether the range should be included

Type: 
boolean

SearchOptions

Options to customize search in RangeGroup#search

Type:
  • object
Properties
NameTypeAttributesDefaultDescription
exclboolean<optional>
false

Whether element should be treated like an exclusive bound of a range. This allows you to search for range boundaries, in addition to regular elements.

endboolean<optional>
false

When excl is true, whether element should be treated as an exclusive start (false) or end (true) range boundary

firstnumber<optional>
0

Inclusive lower bound into RangeGroup#ranges for the search. If less than zero, zero is used.

lastnumber<optional>
-1

Inclusive upper bound into RangeGroup#ranges for the search. A negative value counts from the end, clamping to zero, e.g. -1 is equivalent to this.ranges.length-1. A positive value counts from the start, clamping to the last element.

SearchResult

Type:
  • object
Properties
NameTypeAttributesDescription
indexnumber

Lower bound index; e.g. the position where element could be inserted to keep ranges sorted, or the range that contains element

hasboolean

Whether the range at index contains the element

startRangeType~CompareResult<nullable>

Comparison with the Range#start from index. This will be null if the search bounds (as given by first/last) were empty, or index is beyond the last range (never when has=true). Comparison is made with element as a

endRangeType~CompareResult<nullable>

Comparison with the bounding Range#end. Comparison is made with element as a. The range end came from depends on whether a match was found or not:

  • has=true: The end from index. Will be null if start equaled the element, in which case the end comparison was skipped. You can manually compare the end if its needed.
  • has=false: The end from index-1. Will be null if this is outside the search bounds (as given by first/last), including when the search bounds are empty.

SelfUnionOptions

Options to customize RangeGroup#selfUnion behavior.

Type:
  • object
Properties
NameTypeAttributesDefaultDescription
filterRangeGroup~Filter<optional>
null

Filter function to apply to each range before unioning. This is useful for filtering by Range#a or Range#b nullity, as returned by RangeGroup#diff.

boolboolean<optional>
false

If true, a boolean is returned from the method instead, indicating whether any resulting ranges would be output. See RangeGroup#hasSelfUnion

copyboolean<optional>
false

If true, a self-unioned copy is returned, rather than performing the modification in-place. See RangeGroup#toSelfUnioned