DualMap (dual_map_ex v0.2.2)

A DualMap is simply a dual-entry map struct that allows you to reference pairs of data using both, a key or a value. In a DualMap you can look up a value from its key or a key from its value.

In simple terms we could say that a DualMap is a map where there is no difference between key and value, both can be either one or the other.

How does it work?

A DualMap actually stores 2 maps, a direct one with the key => value pairs, and a inveted one with the value => key pairs.

To create a new DualMap you must use the DualMap.new function.

DualMap.new()

Let's see some examples:

iex> dm = DualMap.new()
[]
iex> DualMap.put(dm, [
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]
iex> DualMap.delete(dm, "192.168.0.3")
[
  {"ns1", "192.168.0.2"},
  {"ns3", "192.168.0.4"}
]

Summary

Types

t()

DualMap struct

Functions

Return de size of the DualMap counting the number of pairs.

Delete one or many pair of datas and returns the DualMap without that pairs. The pair is found looking for key both internal maps, so that it is possible to reference the pair both by its key and by its value.

Checks if two DualMaps are equal.

Just as get/3 but do not accept default parameter. If the key exists in any of the internal maps, will return the tuple {:ok, value}, if not will return :error.

Work equals to fetch/3 but return a value (as get/3) or erroring out if key doesn't exists.

Returns the value asociated to key in any of the internal maps. If key does not exists, default or nil is returned.

Return the complete directed or inverted internal map.

Checks if key exists within DualMap.

Return a list with all the keys of the directed or inverted internal map.

Checks if the pair key_value (a tuple size 2) exists in any of the internal maps either as key => value or as value => key.

Returns an empty DualMap struct.

Returns a DualMap struct initialized with the values indicated in the second argument. As the new/1 function, the order of the master keys are important for posterior operations with the struct.

Insert or replace one or more pairs of datas in a DualMap.

Return a list of the pairs {key, value} taking the directed internal map. This function is used by inspect to print the DualMap.

Return a list with all the values of the directed or inverted internal map.

Types

t()

@type t() :: %DualMap{__data: term()}

DualMap struct

Functions

count(dual_map)

@spec count(t()) :: pos_integer()

Return de size of the DualMap counting the number of pairs.

delete(dual_map, key)

@spec delete(t(), keys :: any() | list()) :: t()

Delete one or many pair of datas and returns the DualMap without that pairs. The pair is found looking for key both internal maps, so that it is possible to reference the pair both by its key and by its value.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

iex> DualMap.delete(dm, "192.168.0.3")
[
  {"ns1", "192.168.0.2"},
  {"ns3", "192.168.0.4"}
]

# Or if you want to delete many...
iex> DualMap.delete(dm, ["ns2", "192.168.0.2"])
[{"ns3", "192.168.0.4"}]

equal?(dual_map1, dual_map2)

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

Checks if two DualMaps are equal.

Two maps are considered to be equal if both internal maps contains the same keys and values.

fetch(dual_map, key)

@spec fetch(t(), any()) :: {:ok, any()} | :error

Just as get/3 but do not accept default parameter. If the key exists in any of the internal maps, will return the tuple {:ok, value}, if not will return :error.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])

iex> DualMap.fetch(dm, "192.168.0.4")
{:ok, "ns3"}

iex> DualMap.fetch(dm, "ns3")
{:ok, "192.168.0.4"}

iex> DualMap.fetch(dm, "192.168.0.6")
:error

fetch!(dual_map, key)

@spec fetch!(t(), any()) :: any()

Work equals to fetch/3 but return a value (as get/3) or erroring out if key doesn't exists.

get(dual_map, key, default \\ nil)

@spec get(t(), key :: any(), default :: any()) :: any()

Returns the value asociated to key in any of the internal maps. If key does not exists, default or nil is returned.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

iex> DualMap.get(dm, "192.168.0.4")
"ns3"

iex> DualMap.get(dm, "ns3")
"192.168.0.4"

get_map(dual_map, opts \\ nil)

@spec get_map(t(), opts :: :inverted | nil) :: map()

Return the complete directed or inverted internal map.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

iex> DualMap.get_map(dm)
%{
  "ns1" => "192.168.0.2",
  "ns2" => "192.168.0.3",
  "ns3" => "192.168.0.4"
}

iex> DualMap.get_map(dm, :inverted)
%{
  "192.168.0.2" => "ns1",
  "192.168.0.3" => "ns2",
  "192.168.0.4" => "ns3"
}

has?(dual_map, key_value)

@spec has?(t(), key :: any()) :: boolean()

Checks if key exists within DualMap.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

iex> DualMap.has?(dm, "192.168.0.4")
true

iex> DualMap.has?(dm, "ns2")
true

iex> DualMap.has?(dm, "ns5")
false

keys(dual_map, opts \\ nil)

@spec keys(t(), opts :: :inverted | nil) :: list()

Return a list with all the keys of the directed or inverted internal map.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])

iex> DualMap.keys(dm)
["ns1", "ns2", "ns3"]

iex> DualMap.keys(dm, :inverted)
["192.168.0.2", "192.168.0.3", "192.168.0.4"]

member?(dual_map, arg)

@spec member?(t(), key_value :: {any(), any()}) :: boolean()

Checks if the pair key_value (a tuple size 2) exists in any of the internal maps either as key => value or as value => key.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]
iex> DualMap.member?(dm, {"192.168.0.4", "ns3"})
true

iex> DualMap.member?(dm, {"ns3", "192.168.0.4"})
true

iex> DualMap.member?(dm, {"ns1", "192.168.0.4"})
false

new()

@spec new() :: t()

Returns an empty DualMap struct.

Examples

iex> DualMap.new({:hostname})
[]

new(values)

@spec new({any(), any()} | [tuple()]) :: t()

Returns a DualMap struct initialized with the values indicated in the second argument. As the new/1 function, the order of the master keys are important for posterior operations with the struct.

Examples

# Initializing with one pair of values
iex> DualMap.new({"ns1", "192.168.0.2"})
[{"ns1", "192.168.0.2"}]

# Initializing with more than one pair of values
iex> DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

put(dual_map, arg2)

@spec put(t(), {key :: any(), value :: any()} | [tuple()]) :: t()

Insert or replace one or more pairs of datas in a DualMap.

Examples

iex> dm = DualMap.new()
[]

# Inserting/replacing many
iex> DualMap.put(dm, [
  {"192.168.0.4", "ns3"},
  {"192.168.0.3", "ns2"},
  {"192.168.0.2", "ns1"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

# Or inserting just one
iex> DualMap.put(dm, {"192.168.0.4", "ns3"})
[{"ns3", "192.168.0.4"}]

to_list(dual_map, option \\ nil)

Return a list of the pairs {key, value} taking the directed internal map. This function is used by inspect to print the DualMap.

If you also pass the option :pairs_inverted, the list returned will have the pairs with key/value taking de inverted internal map.

values(dual_map, opts \\ nil)

@spec values(t(), opts :: :inverted | nil) :: list()

Return a list with all the values of the directed or inverted internal map.

Examples

iex> dm = DualMap.new([
  {"ns3", "192.168.0.4"},
  {"ns2", "192.168.0.3"},
  {"ns1", "192.168.0.2"}
])
[
  {"ns1", "192.168.0.2"},
  {"ns2", "192.168.0.3"},
  {"ns3", "192.168.0.4"}
]

iex> DualMap.values(dm)
["192.168.0.2", "192.168.0.3", "192.168.0.4"]

iex> DualMap.values(dm, :inverted)
["ns1", "ns2", "ns3"]