All files / collections/src arrayMultiMap.ts

80% Statements 20/25
37.5% Branches 3/8
100% Functions 6/6
79.16% Lines 19/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60  2x 2x 2x               27x 2x               27x 27x 27x   27x 21x         43x 43x       4x 4x 2x   2x   4x       2x                     2x      
import { Entry } from "@benneq/object";
import { AbstractMultiMap } from "./abstractMultiMap";
import { deleteFirst } from "@benneq/array";
import { computeIfAbsent } from "@benneq/map";
 
/**
 * An {@link ArrayMultiMap} can contain the same value multiple times per key.
 *
 * @typeParam K - the key type
 * @typeParam V - the value type
 */
export class ArrayMultiMap<K, V> extends AbstractMultiMap<K, V> {
  #value;
 
  /**
   * Create a new {@link ArrayMultiMap} from the given entries.
   *
   * @param iterable - the optional {@link Iterable} of entries
   */
  constructor(iterable?: Iterable<Entry<K, V>>) {
    const value = new Map<K, V[]>();
    super(value);
    this.#value = value;
 
    if (iterable) {
      this.addAll(iterable);
    }
  }
 
  add(key: K, value: V): this {
    (computeIfAbsent(this.#value)(key, () => []) as V[]).push(value);
    return this;
  }
 
  set(key: K, values: Iterable<V>): this {
    const value = [...values];
    if (value.length) {
      this.#value.set(key, value);
    } else {
      this.#value.delete(key);
    }
    return this;
  }
 
  delete(key: K, value?: V): boolean {
    Iif (value) {
      const values = this.#value.get(key);
      Iif (!values || !deleteFirst<V>(value)(values)) {
        return false;
      }
 
      Iif (values.length) {
        return true;
      }
    }
 
    return this.#value.delete(key);
  }
}