@rimbu/bimultimap
Version:
A bidirectional immutable MultiMap of keys and values for TypeScript
906 lines (897 loc) • 31 kB
text/typescript
import type { RSet } from '@rimbu/collection-types';
import type {
KeyValue,
WithKeyValue,
} from '@rimbu/collection-types/map-custom';
import type {
ArrayNonEmpty,
RelatedTo,
ToJSON,
TraverseState,
} from '@rimbu/common';
import type { MultiMap } from '@rimbu/multimap';
import type {
FastIterable,
Reducer,
Stream,
StreamSource,
Streamable,
} from '@rimbu/stream';
export interface BiMultiMapBase<
K,
V,
Tp extends BiMultiMapBase.Types = BiMultiMapBase.Types,
> extends FastIterable<[K, V]> {
/**
* Returns the `context` associated to this collection instance.
*/
readonly context: WithKeyValue<Tp, K, V>['context'];
/**
* Returns the MultiMap representation of the key to value mapping.
* @example
* ```ts
* HashBiMultiMap.of([1, 10], [1, 20]).keyValueMap.toArray()
* // => [[1, [10, 20]]
* ```
*/
readonly keyValueMultiMap: WithKeyValue<Tp, K, V>['keyValueMultiMap'];
/**
* Returns the MultiMap representation of the value to key mapping.
* @example
* ```ts
* HashBiMultiMap.of([10, 1], [20, 1]).valueKeyMap.toArray()
* // => [[1, [10, 20]]
* ```
*/
readonly valueKeyMultiMap: WithKeyValue<Tp, K, V>['valueKeyMultiMap'];
/**
* Returns false since this collection is known to be non-empty.
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).isEmpty // => false
* ```
*/
readonly isEmpty: boolean;
/**
* Returns the number of keys
* @example
* ```ts
* HashBiMultiMap.of([1, 10], [1, 20]).keySize // => 1
* ```
*/
readonly keySize: number;
/**
* Returns the number of entries
* @example
* ```ts
* HashBiMultiMap.of([1, 10], [2, 10]).keySize // => 2
* ```
*/
readonly size: number;
/**
* Returns a `Stream` containing all entries of this collection as tuples of key and value.
* @example
* ```ts
* HashBiMultiMap.of([1, 10], [1, 20]).stream().toArray() // => [[1, 10], [1, 20]]
* ```
*/
stream(): Stream<[K, V]>;
/**
* Returns a `Stream` containing all keys of this collection.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).streamKeys().toArray() // => [1, 2]
* ```
*/
streamKeys(): Stream<K>;
/**
* Returns a `Stream` containing all values of this collection.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).streamValues().toArray() // => ['a', 'b']
* ```
*/
streamValues(): Stream<V>;
/**
* Returns the collection as a .NonEmpty type
* @throws RimbuError.EmptyCollectionAssumedNonEmptyError if the collection is empty
* @example
* ```ts
* HashBiMultiMap.empty<number, number>().assumeNonEmpty() // => throws
* const m: HashBiMultiMap<number, number> = HashBiMultiMap.of([1, 1], [2, 2])
* const m2: HashBiMultiMap.NonEmpty<number, number> = m // => compiler error
* const m3: HashBiMultiMap.NonEmpty<number, number> = m.assumeNonEmpty()
* ```
* @note returns reference to this collection
*/
assumeNonEmpty(): WithKeyValue<Tp, K, V>['nonEmpty'];
/**
* Returns true if there is at least one entry in the collection, and instructs the compiler to treat the collection
* as a .NonEmpty type.
* @example
* ```ts
* const m: HashBiMultiMap<number, number> = HashBiMultiMap.of([1, 1], [2, 2])
* m.stream().first(0) // compiler allows fallback value since the Stream may be empty
* if (m.nonEmpty()) {
* m.stream().first(0) // compiler error: fallback value not allowed since Stream is not empty
* }
* ```
*/
nonEmpty(): this is WithKeyValue<Tp, K, V>['nonEmpty'];
/**
* Returns true if the given `key` is present in the collection.
* @param key - the key to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b'])
* m.hasKey(2) // => true
* m.hasKey(3) // => false
* ```
*/
hasKey<UK = K>(key: RelatedTo<K, UK>): boolean;
/**
* Returns true if the given `value` is present in the collection.
* @param value - the value to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b'])
* m.hasKey('a') // => true
* m.hasKey('z') // => false
* ```
*/
hasValue<UV = V>(key: RelatedTo<V, UV>): boolean;
/**
* Returns true if the given key and value entry is in the collection.
* @param key - the entry key to look for
* @param value - the entry value to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b'])
* m.hasEntry(2, 'b') // => true
* m.hasEntry(2, 'c') // => false
* ```
*/
hasEntry<UK = K, UV = V>(
key: RelatedTo<K, UK>,
value: RelatedTo<V, UV>
): boolean;
/**
* Returns the collection with the given `key` associated to the given `value`.
* @param key - the entry key to add
* @param value - the entry value to add
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).add(1, 2).toArray()
* // => [[1, 1], [1, 2], [2, 2]]
* ```
*/
add(key: K, value: V): WithKeyValue<Tp, K, V>['nonEmpty'];
/**
* Returns the collection with the entries from the given `StreamSource` `entries` added.
* @param entries - a `StreamSource` containing tuples with a key and value
* @example
* ```ts
* HashBiMultiMap.of([1, 1]).addEntries([[2, 2], [1, 3]]).toArray()
* // => [[1, 1], [1, 3], [2, 2]]
* ```
*/
addEntries(
entries: StreamSource.NonEmpty<readonly [K, V]>
): WithKeyValue<Tp, K, V>['nonEmpty'];
addEntries(
entries: StreamSource<readonly [K, V]>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection with the values from the given `values` StreamSource associated
* with the given `key`.
* @param key - the entry key
* @param values - a `StreamSource` containing values to associate with the given `key`
* @example
* ```ts
* HashBiMultiMap.of([1, 1]).setValues(1, [2, 3]).toArray()
* // => [[1, 1], [1, 2], [1, 3]]
* ```
*/
setValues(
key: K,
values: StreamSource.NonEmpty<V>
): WithKeyValue<Tp, K, V>['nonEmpty'];
setValues(key: K, values: StreamSource<V>): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection with the keys from the given `keys` StreamSource associated
* with the given `value`.
* @param value - the entry value
* @param keys - a `StreamSource` containing keys to associate with the given `value`
* @example
* ```ts
* HashBiMultiMap.of([1, 1]).setKeys(1, [2, 3]).toArray()
* // => [[1, 1], [2, 1], [3, 1]]
* ```
*/
setKeys(
value: V,
keys: StreamSource.NonEmpty<K>
): WithKeyValue<Tp, K, V>['nonEmpty'];
setKeys(value: V, keys: StreamSource<K>): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns a collection containing the values associated with the given `key`.
* @param key - the key of which to find the values
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [1, 2]);
* m.getValues(1).toArray()
* // => [1, 2]
* m.getValues(5).toArray()
* // => []
* ```
*/
getValues<UK = K>(
key: RelatedTo<K, UK>
): WithKeyValue<Tp, K, V>['keyMultiMapValues'];
/**
* Returns a collection containing the keys associated with the given `value`.
* @param value - the value of which to find the keys
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [2, 1]);
* m.getKeys(1).toArray()
* // => [1, 2]
* m.getKeys(5).toArray()
* // => []
* ```
*/
getKeys<UV = V>(
value: RelatedTo<V, UV>
): WithKeyValue<Tp, K, V>['valueMultiMapValues'];
/**
* Returns the collection where the entries associated with given `key` are removed if it was part of the collection.
* @param key - the key of the entries to remove
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [1, 2])
* m.removeKey(2).toArray() // => [1, 2]
* m.removeKey(3) === m // true
* ```
* @note guarantees same object reference if the key is not present
*/
removeKey<UK = K>(key: RelatedTo<K, UK>): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection where the entries associated with each key in given `keys` are removed if they were present.
* @param keys - a `StreamSource` of keys to remove
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [2, 2])
* m.removeKeys([1, 3]).toArray() // => [[2, 2]]
* m.removeKeys([1, 3, 2]).toArray() // => []
* m.removeKeys([3, 4, 5]) === m // => true
* ```
* @note guarantees same object reference if none of the keys are present
*/
removeKeys<UK = K>(
keys: StreamSource<RelatedTo<K, UK>>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection where the entries associated with given `value` are removed if it was part of the collection.
* @param value - the value of the entries to remove
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 2], [2, 2])
* m.removeValue(2).toArray() // => [1, 2]
* m.removeValue(3) === m // true
* ```
* @note guarantees same object reference if the key is not present
*/
removeValue<UV = V>(
value: RelatedTo<V, UV>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection where the entries associated with each value in given `values` are removed if they were present.
* @param values - a `StreamSource` of values to remove
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [2, 2])
* m.removeValues([1, 3]).toArray() // => [[2, 2]]
* m.removeValues([1, 3, 2]).toArray() // => []
* m.removeValues([3, 4, 5]) === m // => true
* ```
* @note guarantees same object reference if none of the keys are present
*/
removeValues<UV = V>(
values: StreamSource<RelatedTo<V, UV>>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection where the entry with given `key` or `value` is removed if present.
* @param key - the entry key
* @param value - the entry value
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [2, 2])
* m.removeEntry(2, 2).toArray() // => [[1, 1]]
* m.removeEntry(1, 2).toArray() // => [[1, 1], [2, 2]]
* m.removeEntry(3, 3) === m // => true
* ```
*/
removeEntry<UK = K, UV = V>(
key: RelatedTo<K, UK>,
value: RelatedTo<V, UV>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns the collection where the entries in the given `entries` StreamSource are removed if present.
* @param entries - a StreamSource containing entries to remove
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 1], [2, 2])
* m.removeEntries([[2, 2], [2, 3]]).toArray() // => [[1, 1]]
* m.removeEntries([[1, 2], [4, 3]]).toArray() // => [[1, 1], [2, 2]]
* m.removeEntries([[3, 3]]) === m // => true
* ```
*/
removeEntries<UK = K, UV = V>(
entries: StreamSource<[RelatedTo<K, UK>, RelatedTo<V, UV>]>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Performs given function `f` for each entry of the collection, using given `state` as initial traversal state.
* @param f - the function to perform for each entry, receiving:<br/>
* - `entry`: the next tuple of a key and value<br/>
* - `index`: the index of the element<br/>
* - `halt`: a function that, if called, ensures that no new elements are passed
* @param options - (optional) an object containing the following properties:<br/>
* - state: (optional) the traversal state
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b'], [3, 'c']).forEach((entry, i, halt) => {
* console.log([entry[1], entry[0]]);
* if (i >= 1) halt();
* })
* // => logs ['a', 1] ['b', 2]
* ```
* @note O(N)
*/
forEach(
f: (entry: [K, V], index: number, halt: () => void) => void,
options?: { state?: TraverseState }
): void;
/**
* Returns a collection containing only those entries that satisfy given `pred` predicate.
* @param pred - a predicate function receiving:<br/>
* - `entry`: the next entry<br/>
* - `index`: the entry index<br/>
* - `halt`: a function that, when called, ensures no next elements are passed
* @param options - (optional) an object containing the following properties:<br/>
* - negate: (default: false) when true will negate the given predicate
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b'], [3, 'c']).filter(entry => entry[0] === 2 || entry[1] === 'c').toArray()
* // => [[2, 'b'], [3, 'c']]
* ```
*/
filter(
pred: (entry: [K, V], index: number, halt: () => void) => boolean,
options?: { negate?: boolean }
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns an array containing all entries in this collection.
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b']).toArray() // => [[1, 'a'], [2, 'b']]
* ```
* @note O(log(N))
*/
toArray(): [K, V][];
/**
* Returns a string representation of this collection.
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b']).toString() // => HashBiMultiMap(1 <=> ['a'], 2 <=> ['b'])
* ```
*/
toString(): string;
/**
* Returns a JSON representation of this collection.
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b']).toJSON() // => { dataType: 'HashBiMultiMap', value: [[1, ['a']], [2, ['b']]] }
* ```
*/
toJSON(): ToJSON<[K, V[]][], this['context']['typeTag']>;
/**
* Returns a builder object containing the entries of this collection.
* @example
* ```ts
* const builder: HashBiMultiMap.Builder<number, string> = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* ```
*/
toBuilder(): WithKeyValue<Tp, K, V>['builder'];
}
export namespace BiMultiMapBase {
export interface NonEmpty<
K,
V,
Tp extends BiMultiMapBase.Types = BiMultiMapBase.Types,
> extends BiMultiMapBase<K, V, Tp>,
Streamable.NonEmpty<[K, V]> {
/**
* Returns the non-empty MultiMap representation of the key to value mapping.
* @example
* ```ts
* HashBiMultiMap.of([1, 10], [1, 20]).keyValueMap.toArray()
* // => [[1, [10, 20]]
* ```
*/
readonly keyValueMultiMap: WithKeyValue<
Tp,
K,
V
>['keyValueMultiMapNonEmpty'];
/**
* Returns the MultiMap representation of the value to key mapping.
* @example
* ```ts
* HashBiMultiMap.of([10, 1], [20, 1]).valueKeyMap.toArray()
* // => [[1, [10, 20]]
* ```
*/
readonly valueKeyMultiMap: WithKeyValue<
Tp,
K,
V
>['valueKeyMultiMapNonEmpty'];
/**
* Returns false since this collection is known to be non-empty.
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).isEmpty // => false
* ```
*/
readonly isEmpty: false;
/**
* Returns a non-empty `Stream` containing all entries of this collection as tuples of key and value.
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).stream().toArray() // => [[1, 1], [2, 2]]
* ```
*/
stream(): Stream.NonEmpty<[K, V]>;
/**
* Returns a non-empty `Stream` containing all keys of this collection.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).streamKeys().toArray() // => [1, 2]
* ```
*/
streamKeys(): Stream.NonEmpty<K>;
/**
* Returns a non-empty `Stream` containing all values of this collection.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).streamValues().toArray() // => ['a', 'b']
* ```
*/
streamValues(): Stream.NonEmpty<V>;
/**
* Returns this collection typed as a 'possibly empty' collection.
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).asNormal(); // type: HashBiMultiMap<number, number>
* ```
*/
asNormal(): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns true since this collection is known to be non-empty
* @example
* ```ts
* HashBiMultiMap.of([1, 1], [2, 2]).nonEmpty() // => true
* ```
*/
nonEmpty(): this is WithKeyValue<Tp, K, V>['nonEmpty'];
/**
* Returns the collection with the entries from the given `StreamSource` `entries` added.
* @param entries - a `StreamSource` containing tuples with a key and value
* @example
* ```ts
* HashBiMultiMap.of([1, 1]).addEntries([[2, 2], [1, 3]]).toArray()
* // => [[1, 1], [1, 3], [2, 2]]
* ```
*/
addEntries(
entries: StreamSource<readonly [K, V]>
): WithKeyValue<Tp, K, V>['nonEmpty'];
}
export interface Factory<
UK = unknown,
UV = unknown,
Tp extends BiMultiMapBase.Types = BiMultiMapBase.Types,
> {
/**
* Returns the (singleton) empty instance of this type and context with given key and value types.
* @example
* ```ts
* HashBiMultiMap.empty<number, string>() // => HashBiMultiMap<number, string>
* HashBiMultiMap.empty<string, boolean>() // => HashBiMultiMap<string, boolean>
* ```
*/
empty<K extends UK, V extends UV>(): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns an immutable BiMultiMap, containing the given `entries`.
* @param entries - a non-empty array of key-value entries
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b']) // => HashBiMultiMap.NonEmpty<number, string>
* ```
*/
of<K extends UK, V extends UV>(
...entries: ArrayNonEmpty<readonly [K, V]>
): WithKeyValue<Tp, K, V>['nonEmpty'];
/**
* Returns an immutable BiMultiMap, containing the entries in the given `sources` `StreamSource` instances.
* @param sources - an array of `StreamSource` instances contaning key-value entries
* @example
* ```ts
* HashBiMultiMap.from([[1, 'a'], [2, 'b']]) // => HashBiMultiMap.NonEmpty<number, string>
* ```
*/
from<K extends UK, V extends UV>(
...sources: ArrayNonEmpty<StreamSource.NonEmpty<readonly [K, V]>>
): WithKeyValue<Tp, K, V>['nonEmpty'];
from<K extends UK, V extends UV>(
...sources: ArrayNonEmpty<StreamSource<readonly [K, V]>>
): WithKeyValue<Tp, K, V>['normal'];
/**
* Returns an empty `BiMultiMap` builder instance.
* @example
* ```ts
* HashBiMultiMap.builder<number, string>() // => HashBiMultiMap.Builder<number, string>
* ```
*/
builder<K extends UK, V extends UV>(): WithKeyValue<Tp, K, V>['builder'];
/**
* Returns a `Reducer` that adds received tuples to a BiMultiMap and returns the BiMultiMap as a result. When a `source` is given,
* the reducer will first create a BiMultiMap from the source, and then add tuples to it.
* @param source - (optional) an initial source of tuples to add to
* @example
* ```ts
* const someSource = BiMultiMap.of([1, 'a'], [2, 'b']);
* const result = Stream.of([1, 'c'], [3, 'a']).reduce(BiMultiMap.reducer(someSource))
* result.toArray() // => [[1, 'a'], [1, 'c'], [2, 'b'], [3, 'a']]
* ```
* @note uses a builder under the hood. If the given `source` is a BiMultiMap in the same context, it will directly call `.toBuilder()`.
*/
reducer<K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
): Reducer<readonly [K, V], WithKeyValue<Tp, K, V>['normal']>;
}
export interface Context<
UK,
UV,
Tp extends BiMultiMapBase.Types = BiMultiMapBase.Types,
> extends BiMultiMapBase.Factory<UK, UV, Tp> {
readonly _fixTypes: readonly [UK, UV];
/**
* A string tag defining the specific collection type
* @example
* ```ts
* HashBiMultiMap.defaultContext().typeTag // => 'HashBiMultiMap'
* ```
*/
readonly typeTag: string;
readonly _types: Tp;
readonly keyValueMultiMapContext: WithKeyValue<
Tp,
UK,
UV
>['keyValueMultiMapContext'];
readonly valueKeyMultiMapContext: WithKeyValue<
Tp,
UK,
UV
>['valueKeyMultiMapContext'];
}
export interface Builder<
K,
V,
Tp extends BiMultiMapBase.Types = BiMultiMapBase.Types,
> {
/**
* Returns the amount of entries in the builder.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).toBuilder().size
* // => 2
* ```
*/
readonly size: number;
/**
* Returns true if there are no entries in the builder.
* @example
* ```ts
* HashBiMultiMap.of([[1, 'a'], [2, 'b']]).toBuilder().isEmpty
* // => false
* ```
*/
readonly isEmpty: boolean;
/**
* Returns true if the given `key` is present in the builder.
* @param key - the key to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.hasKey(2) // => true
* m.hasKey(3) // => false
* ```
*/
hasKey<UK = K>(key: RelatedTo<K, UK>): boolean;
/**
* Returns true if the given `value` is present in the builder.
* @param value - the value to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.hasValue('a') // => true
* m.hasValue('z') // => false
* ```
*/
hasValue<UV = V>(value: RelatedTo<V, UV>): boolean;
/**
* Returns true if the given `key` `value` entry is present in the builder.
* @param key - the key to look for
* @param value - the value to look for
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.hasEntry(1, 'a') // => true
* m.hasEntry(1, 'z') // => false
* ```
*/
hasEntry<UK = K, UV = V>(
key: RelatedTo<K, UK>,
value: RelatedTo<V, UV>
): boolean;
/**
* Returns a collection representing the values currently associated with given `key`.
* @param key - the key for which to find the values
*
* @note since it is unsafe to return the internal builder object, the result colleciton will
* be build upon each call to getValues.
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.getValues(1).toArray() // => ['a']
* m.getValues(3).toArray() // => []
* ```
*/
getValues<UK = K>(
key: RelatedTo<K, UK>
): WithKeyValue<Tp, K, V>['keyMultiMapValues'];
/**
* Returns a collection representing the keys currently associated with given `value`.
* @param value - the value for which to find the keys
*
* @note since it is unsafe to return the internal builder object, the result colleciton will
* be build upon each call to getKeys.
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.getKeys('a').toArray() // => [1]
* m.getKeys('z').toArray() // => []
* ```
*/
getKeys<UV = V>(
value: RelatedTo<V, UV>
): WithKeyValue<Tp, K, V>['valueMultiMapValues'];
/**
* Sets the values associated to given `key` to the values in the given `values` StreamSource.
* @param key - the key to which to associate the values
* @param values - a StreamSource containing the values to associate to the key
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.setValues(1, ['b', 'c']).getValues(1).toArray() // => ['b', 'c']
* ```
*/
setValues(key: K, values: StreamSource<V>): boolean;
/**
* Sets the keys associated to given `value` to the keys in the given `keys` StreamSource.
* @param value - the value to which to associate the keys
* @param keys - a StreamSource containing the keys to associate to the value
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.setKeys('a', [3, 4]).getKeys('a').toArray() // => [3, 4]
* ```
*/
setKeys(value: V, keys: StreamSource<K>): boolean;
/**
* Associates given `key` with given `value` in the builder.
* @param key - the entry key
* @param value - the entry value
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.set(1, 'a') // => false
* m.set(1, 'b') // => true
* ```
*/
add(key: K, value: V): boolean;
/**
* Adds given `entries` to the builder.
* @param entries - a `StreamSource` containing the entries to add
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.addEntries([1, 'a'], [3, 'c']]) // => true
* m.addEntries([]) // => false
* ```
*/
addEntries(entries: StreamSource<readonly [K, V]>): boolean;
/**
* Removes the entries related to given `key` from the builder.
* @param key - the key to remove
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeKey(2) // => true
* m.removeKey(3) // => false
* ```
*/
removeKey<UK = K>(key: RelatedTo<K, UK>): boolean;
/**
* Removes the entries related to the given `keys` `StreamSource` from the builder.
* @param keys - the `StreamSource` containing the keys to remove.
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeKeys([3, 4, 5]) // => false
* m.removeKeys([1, 10]) // => true
* ```
*/
removeKeys<UK = K>(keys: StreamSource<RelatedTo<K, UK>>): boolean;
/**
* Removes the entries related to given `value` from the builder.
* @param value - the value to remove
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeValue('b') // => true
* m.removeValue('c') // => false
* ```
*/
removeValue<UV = V>(value: RelatedTo<V, UV>): boolean;
/**
* Removes the entries related to the given `values` `StreamSource` from the builder.
* @param values - the `StreamSource` containing the values to remove.
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeValues(['c', 'd', 'e']) // => false
* m.removeValues(['a', 'e']) // => true
* ```
*/
removeValues<UV = V>(values: StreamSource<RelatedTo<V, UV>>): boolean;
/**
* Removes the entry of given `key` and `value` from the builder.
* @param key - the entry key
* @param value - the entry value
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeEntry(1, 'c') // => false
* m.removeEntry(1, 'a') // => true
* ```
*/
removeEntry<UK = K, UV = V>(
key: RelatedTo<K, UK>,
value: RelatedTo<V, UV>
): boolean;
/**
* Removes the entries in the given `entries` `StreamSource` from the builder.
* @param entries - the `StreamSource` containing the entries to remove.
* @returns true if the data in the builder has changed
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* m.removeEntries([[1, 'c'], ['2', 'a']]) // => false
* m.removeEntries([[1, 'a']]) // => true
* ```
*/
removeEntries<UK = K, UV = V>(
entries: StreamSource<[RelatedTo<K, UK>, RelatedTo<V, UV>]>
): boolean;
/**
* Performs given function `f` for each entry of the builder.
* @param f - the function to perform for each element, receiving:<br/>
* - `entry`: the next key-value entry<br/>
* - `index`: the index of the element<br/>
* - `halt`: a function that, if called, ensures that no new elements are passed
* @throws RibuError.ModifiedBuilderWhileLoopingOverItError if the builder is modified while
* looping over it
* @example
* ```ts
* HashBiMultiMap.of([1, 'a'], [2, 'b'], [3, 'c']).toBuilder().forEach((entry, i, halt) => {
* console.log([entry[1], entry[0]]);
* if (i >= 1) halt();
* })
* // => logs ['a', 1] ['b', 2]
* ```
* @note O(N)
*/
forEach(
f: (entry: [K, V], index: number, halt: () => void) => void,
options?: { state?: TraverseState }
): void;
/**
* Returns an immutable collection instance containing the entries in this builder.
* @example
* ```ts
* const m = HashBiMultiMap.of([1, 'a'], [2, 'b']).toBuilder()
* const m2: HashBiMultiMap<number, string> = m.build()
* ```
*/
build(): WithKeyValue<Tp, K, V>['normal'];
}
/**
* Utility interface that provides higher-kinded types for this collection.
*/
export interface Types extends KeyValue {
/**
* The collection context type (higher-kinded type).
*/
readonly context: BiMultiMapBase.Context<this['_K'], this['_V']>;
/**
* The 'normal' collection type (higher-kinded type).
*/
readonly normal: BiMultiMapBase<this['_K'], this['_V']>;
/**
* The 'non-empty' collection type (higher-kinded type).
*/
readonly nonEmpty: BiMultiMapBase.NonEmpty<this['_K'], this['_V']>;
/**
* The 'builder' collection type (higher-kinded type).
*/
readonly builder: BiMultiMapBase.Builder<this['_K'], this['_V']>;
/**
* The key to value multimap context type (higher-kinded type).
*/
readonly keyValueMultiMapContext: MultiMap.Context<this['_K'], this['_V']>;
/**
* The value to key multimap context type (higher-kinded type).
*/
readonly valueKeyMultiMapContext: MultiMap.Context<this['_V'], this['_K']>;
/**
* The key to value multimap type (higher-kinded type).
*/
readonly keyValueMultiMap: MultiMap<this['_K'], this['_V']>;
/**
* The value to key multimap type (higher-kinded type).
*/
readonly valueKeyMultiMap: MultiMap<this['_V'], this['_K']>;
/**
* The non-empty key to value multimap type (higher-kinded type).
*/
readonly keyValueMultiMapNonEmpty: MultiMap.NonEmpty<
this['_K'],
this['_V']
>;
/**
* The non-empty value to key multimap type (higher-kinded type).
*/
readonly valueKeyMultiMapNonEmpty: MultiMap.NonEmpty<
this['_V'],
this['_K']
>;
/**
* The value set collection type (higher-kinded type).
*/
readonly keyMultiMapValues: RSet<this['_V']>;
/**
* The key set collection type (higher-kinded type).
*/
readonly valueMultiMapValues: RSet<this['_K']>;
}
}