View Source BiMultiMap (BiMap v1.3.0)

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

@type k() :: term()

Key type

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

Value type

Functions

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

Convenience shortcut for delete/3.

Link to this function

delete(bimultimap, key, value)

View Source
@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])
Link to this function

delete_key(bimultimap, key)

View Source
@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])
Link to this function

delete_value(bimultimap, value)

View Source
@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])
Link to this function

equal?(bimultimap1, bimultimap2)

View Source
@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
@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]}
@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]
Link to this function

fetch_keys(bimultimap, value)

View Source
@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]}
Link to this function

fetch_keys!(bimultimap, value)

View Source
@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]
Link to this function

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

View Source
@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]
Link to this function

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

View Source
@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]
Link to this function

has_key?(bimultimap, key)

View Source
@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
Link to this function

has_value?(bimultimap, value)

View Source
@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
@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]
@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"]}
@spec member?(
  t(),
  {k(), v()}
) :: boolean()

Convenience shortcut for member?/3.

Link to this function

member?(bimultimap, key, value)

View Source
@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
@spec new() :: t()

Creates a new bimultimap.

Examples

iex> BiMultiMap.new
BiMultiMap.new([])
@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])
Link to this function

new(enumerable, transform)

View Source
@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}])
@spec put(
  t(),
  {k(), v()}
) :: t()

Convenience shortcut for put/3

Link to this function

put(bimultimap, key, value)

View Source
@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])
@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]}
@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
@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"]
@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]