BiMultiMap (BiMap v1.3.0)

View Source

Bi-directional multimap implementation backed by two multimaps.

Entries in bimap do not follow any order.

BiMultiMaps do not impose any restriction on the key and value type: anything can be a key in a bimap, and also anything can be a value.

BiMultiMaps differ from BiMaps by disallowing duplicates only among key-value pairs, not among keys and values separately. This means it is possible to store [(A, B), (A, C)] or [(X, Z), (Y, Z)] in BiMultiMap.

Keys and values are compared using the exact-equality operator (===).

Example

iex> mm = BiMultiMap.new(a: 1, b: 2, b: 1)
BiMultiMap.new([a: 1, b: 1, b: 2])
iex> BiMultiMap.get(mm, :a)
[1]
iex> BiMultiMap.get_keys(mm, 1)
[:a, :b]
iex> BiMultiMap.put(mm, :a, 3)
BiMultiMap.new([a: 1, a: 3, b: 1, b: 2])

Protocols

BiMultiMap implements Enumerable, Collectable and Inspect protocols.

Summary

Types

k()

Key type

t()
v()

Value type

Functions

Convenience shortcut for delete/3.

Deletes {key, value} pair from bimultimap.

Deletes {key, _} pair from bimultimap.

Deletes {_, value} pair from bimultimap.

Checks if two bimultimaps are equal.

Fetches all values for specific key in bimultimap

Fetches all values for specific key in bimultimap

Fetches all keys for specific value in bimultimap

Fetches all keys for specific value in bimultimap

Gets all values for specific key in bimultimap

Gets all keys for specific value in bimultimap

Checks if bimultimap contains key.

Checks if bimultimap contains value.

Returns all unique keys from bimultimap.

Returns key ➜ [value] mapping of bimultimap.

Convenience shortcut for member?/3.

Checks if bimultimap contains {key, value} pair.

Creates a new bimultimap.

Creates a bimultimap from enumerable of key-value pairs.

Creates a bimultimap from enumerable via transform function returning key-value pairs.

Convenience shortcut for put/3

Inserts {key, value} pair into bimultimap.

Returns value ➜ key mapping of bimultimap.

Returns the number of elements in bimultimap.

Returns list of unique key-value pairs in bimultimap.

Returns all unique values from bimultimap.

Types

k()

@type k() :: term()

Key type

t()

@type t() :: t(term(), term())

t(k, v)

@type t(k, v) :: %BiMultiMap{
  keys: internal_keys(k, v),
  size: internal_size(),
  values: internal_values(k, v)
}

v()

@type v() :: term()

Value type

Functions

delete(bimultimap, kv)

@spec delete(
  t(),
  {k(), v()}
) :: t()

Convenience shortcut for delete/3.

delete(bimultimap, key, value)

@spec delete(t(), k(), v()) :: t()

Deletes {key, value} pair from bimultimap.

If the key does not exist, or value does not match, returns bimultimap unchanged.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, b: 2, c: 2])
iex> BiMultiMap.delete(bimultimap, :b, 2)
BiMultiMap.new([a: 1, c: 2])
iex> BiMultiMap.delete(bimultimap, :c, 3)
BiMultiMap.new([a: 1, b: 2, c: 2])

delete_key(bimultimap, key)

@spec delete_key(t(), k()) :: t()

Deletes {key, _} pair from bimultimap.

If the key does not exist, returns bimultimap unchanged.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, b: 2, b: 3])
iex> BiMultiMap.delete_key(bimultimap, :b)
BiMultiMap.new([a: 1])
iex> BiMultiMap.delete_key(bimultimap, :c)
BiMultiMap.new([a: 1, b: 2, b: 3])

delete_value(bimultimap, value)

@spec delete_value(t(), v()) :: t()

Deletes {_, value} pair from bimultimap.

If the value does not exist, returns bimultimap unchanged.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, b: 2, c: 1])
iex> BiMultiMap.delete_value(bimultimap, 1)
BiMultiMap.new([b: 2])
iex> BiMultiMap.delete_value(bimultimap, 3)
BiMultiMap.new([a: 1, b: 2, c: 1])

equal?(bimultimap1, bimultimap2)

@spec equal?(t(), t()) :: boolean()

Checks if two bimultimaps are equal.

Two bimultimaps are considered to be equal if they contain the same keys and those keys are bound with the same values.

Examples

iex> Map.equal?(BiMultiMap.new([a: 1, b: 2, b: 3]), BiMultiMap.new([b: 2, b: 3, a: 1]))
true
iex> Map.equal?(BiMultiMap.new([a: 1, b: 2, b: 3]), BiMultiMap.new([b: 1, b: 3, a: 2]))
false

fetch(bimultimap, key)

@spec fetch(t(), k()) :: {:ok, [v()]} | :error

Fetches all values for specific key in bimultimap

If key is present in bimultimap with values values, then {:ok, values} is returned. Otherwise, :error is returned.

Examples

iex> BiMultiMap.fetch(BiMultiMap.new(), :a)
:error
iex> bimultimap = BiMultiMap.new([a: 1, c: 1, c: 2])
iex> BiMultiMap.fetch(bimultimap, :a)
{:ok, [1]}
iex> BiMultiMap.fetch(bimultimap, :b)
:error
iex> BiMultiMap.fetch(bimultimap, :c)
{:ok, [1, 2]}

fetch!(bimultimap, key)

@spec fetch!(t(), k()) :: [v()]

Fetches all values for specific key in bimultimap

Raises ArgumentError if the key is absent.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, c: 1, c: 2])
iex> BiMultiMap.fetch!(bimultimap, :a)
[1]
iex> BiMultiMap.fetch!(bimultimap, :c)
[1, 2]

fetch_keys(bimultimap, value)

@spec fetch_keys(t(), v()) :: {:ok, [k()]} | :error

Fetches all keys for specific value in bimultimap

This function is exact mirror of fetch/2.

Examples

iex> BiMultiMap.fetch_keys(BiMultiMap.new, 1)
:error
iex> bimultimap = BiMultiMap.new([a: 1, c: 3, d: 3])
iex> BiMultiMap.fetch_keys(bimultimap, 1)
{:ok, [:a]}
iex> BiMultiMap.fetch_keys(bimultimap, 2)
:error
iex> BiMultiMap.fetch_keys(bimultimap, 3)
{:ok, [:c, :d]}

fetch_keys!(bimultimap, value)

@spec fetch_keys!(t(), v()) :: [k()]

Fetches all keys for specific value in bimultimap

Raises ArgumentError if the key is absent. This function is exact mirror of fetch!/2.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, c: 3, d: 3])
iex> BiMultiMap.fetch_keys!(bimultimap, 1)
[:a]
iex> BiMultiMap.fetch_keys!(bimultimap, 3)
[:c, :d]

get(bimultimap, key, default \\ [])

@spec get(t(), k(), any()) :: [v()] | any()

Gets all values for specific key in bimultimap

If key is present in bimultimap with values values, then values are returned. Otherwise, default is returned (which is [] unless specified otherwise).

Examples

iex> BiMultiMap.get(BiMultiMap.new(), :a)
[]
iex> bimultimap = BiMultiMap.new([a: 1, c: 1, c: 2])
iex> BiMultiMap.get(bimultimap, :a)
[1]
iex> BiMultiMap.get(bimultimap, :b)
[]
iex> BiMultiMap.get(bimultimap, :b, 3)
3
iex> BiMultiMap.get(bimultimap, :c)
[1, 2]

get_keys(bimultimap, value, default \\ [])

@spec get_keys(t(), v(), any()) :: [k()] | any()

Gets all keys for specific value in bimultimap

This function is exact mirror of get/3.

Examples

iex> BiMultiMap.get_keys(BiMultiMap.new, 1)
[]
iex> bimultimap = BiMultiMap.new([a: 1, c: 3, d: 3])
iex> BiMultiMap.get_keys(bimultimap, 1)
[:a]
iex> BiMultiMap.get_keys(bimultimap, 2)
[]
iex> BiMultiMap.get_keys(bimultimap, 2, :b)
:b
iex> BiMultiMap.get_keys(bimultimap, 3)
[:c, :d]

has_key?(bimultimap, key)

@spec has_key?(t(), k()) :: boolean()

Checks if bimultimap contains key.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", b: "bar"])
iex> BiMultiMap.has_key?(bimultimap, :a)
true
iex> BiMultiMap.has_key?(bimultimap, :x)
false

has_value?(bimultimap, value)

@spec has_value?(t(), v()) :: boolean()

Checks if bimultimap contains value.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", b: "bar"])
iex> BiMultiMap.has_value?(bimultimap, "foo")
true
iex> BiMultiMap.has_value?(bimultimap, "moo")
false

keys(bimultimap)

@spec keys(t()) :: [k()]

Returns all unique keys from bimultimap.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, b: 2, b: 3])
iex> BiMultiMap.keys(bimultimap)
[:a, :b]

left(bimultimap)

@spec left(t()) :: %{required(k()) => [v()]}

Returns key ➜ [value] mapping of bimultimap.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", b: "bar", b: "moo"])
iex> BiMultiMap.left(bimultimap)
%{a: ["foo"], b: ["bar", "moo"]}

member?(bimultimap, kv)

@spec member?(
  t(),
  {k(), v()}
) :: boolean()

Convenience shortcut for member?/3.

member?(bimultimap, key, value)

@spec member?(t(), k(), v()) :: boolean()

Checks if bimultimap contains {key, value} pair.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", a: "moo", b: "bar"])
iex> BiMultiMap.member?(bimultimap, :a, "foo")
true
iex> BiMultiMap.member?(bimultimap, :a, "moo")
true
iex> BiMultiMap.member?(bimultimap, :a, "bar")
false

new()

@spec new() :: t()

Creates a new bimultimap.

Examples

iex> BiMultiMap.new
BiMultiMap.new([])

new(enumerable)

@spec new(Enum.t()) :: t()

Creates a bimultimap from enumerable of key-value pairs.

Duplicated pairs are removed; the latest one prevails.

Examples

iex> BiMultiMap.new([a: 1, a: 2])
BiMultiMap.new([a: 1, a: 2])

new(enumerable, transform)

@spec new(Enum.t(), (term() -> {k(), v()})) :: t()

Creates a bimultimap from enumerable via transform function returning key-value pairs.

Examples

iex> BiMultiMap.new([1, 2, 1], fn x -> {x, x * 2} end)
BiMultiMap.new([{1, 2}, {2, 4}])

put(bimultimap, kv)

@spec put(
  t(),
  {k(), v()}
) :: t()

Convenience shortcut for put/3

put(bimultimap, key, value)

@spec put(t(), k(), v()) :: t()

Inserts {key, value} pair into bimultimap.

If {key, value} is already in bimultimap, it is deleted.

Examples

iex> bimultimap = BiMultiMap.new
BiMultiMap.new([])
iex> bimultimap = BiMultiMap.put(bimultimap, :a, 1)
BiMultiMap.new([a: 1])
iex> bimultimap = BiMultiMap.put(bimultimap, :a, 2)
BiMultiMap.new([a: 1, a: 2])
iex> BiMultiMap.put(bimultimap, :b, 2)
BiMultiMap.new([a: 1, a: 2, b: 2])

right(bimultimap)

@spec right(t()) :: %{required(v()) => [k()]}

Returns value ➜ key mapping of bimultimap.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", b: "bar", c: "bar"])
iex> BiMultiMap.right(bimultimap)
%{"foo" => [:a], "bar" => [:b, :c]}

size(bimultimap)

@spec size(t()) :: non_neg_integer()

Returns the number of elements in bimultimap.

The size of a bimultimap is the number of key-value pairs that the map contains.

Examples

iex> BiMultiMap.size(BiMultiMap.new)
0

iex> bimultimap = BiMultiMap.new([a: "foo", a: "bar"])
iex> BiMultiMap.size(bimultimap)
2

to_list(bimultimap)

@spec to_list(t()) :: [{k(), v()}]

Returns list of unique key-value pairs in bimultimap.

Examples

iex> bimultimap = BiMultiMap.new([a: "foo", b: "bar"])
iex> BiMultiMap.to_list(bimultimap)
[a: "foo", b: "bar"]

values(bimultimap)

@spec values(t()) :: [v()]

Returns all unique values from bimultimap.

Examples

iex> bimultimap = BiMultiMap.new([a: 1, b: 2, c: 2])
iex> BiMultiMap.values(bimultimap)
[1, 2]