Swiss.Map (swiss v3.12.0) View Source

A few extra functions to deal with Maps.

Link to this section Summary

Functions

Cuts off a map at the given depth.

Deep merges two maps. Only maps are merged, all other types are overridden.

Applies defaults to a map.

Wrapper around Map.from_struct/1 that tolerates nil.

Fetches a value from a map with indifferent access, i.e. given an atom, returns the value that is keyed by that atom, or by its string equivalent.

Runs Map.put/3 only if pred returns truthy when called on the value.

Runs Map.put/3 only if cond is truthy. Unlike Swiss.Map.put_if/4, takes a function that is called when the condition passes, that should return the value to insert in the map.

Converts an atom-keyed map into a string-keyed map.

Appplies an updater function to all keys in the given map.

Link to this section Functions

Link to this function

cut_depth(map, opts \\ [])

View Source

Specs

cut_depth(map :: map(), opts :: cut_depth_opts) :: map()
when cut_depth_opts: [max_depth: non_neg_integer(), placeholder: any()]

Cuts off a map at the given depth.

This works for nested maps, but also maps nested in lists and tuples.

Options

  • max_depth: Depth at which to cut off at. Defaults to 1.
  • placeholder: Map values that would exceed the maximum depth are replaced by a placeholder. Defaults to an empty map.

Examples

iex> Swiss.Map.cut_depth(%{a: 1, b: 2})
%{a: 1, b: 2}

iex> Swiss.Map.cut_depth(%{a: %{c: 3, d: 4}, b: 2})
%{a: %{}, b: 2}

iex> Swiss.Map.cut_depth(%{a: %{c: 3, d: 4}, b: 2}, max_depth: 2)
%{a: %{c: 3, d: 4}, b: 2}

iex> Swiss.Map.cut_depth(%{a: %{c: 3, d: 4}, b: 2}, placeholder: "%{...}")
%{a: "%{...}", b: 2}

iex> Swiss.Map.cut_depth(%{a: [1, 2], b: [%{a: 2}], c: {1, 2}, d: {%{a: 5}}})
%{a: [1, 2], b: [%{}], c: {1, 2}, d: {%{}}}
Link to this function

deep_merge(map_dest, map_src, max_depth \\ :infinity)

View Source

Specs

deep_merge(map(), map(), non_neg_integer() | :infinity) :: map()

Deep merges two maps. Only maps are merged, all other types are overridden.

Examples

iex> Swiss.Map.deep_merge(%{user: %{id: 42}}, %{user: %{name: "João"}})
%{user: %{id: 42, name: "João"}}

iex> Swiss.Map.deep_merge(
...> %{user: %{id: 42, message: %{id: 22}}},
...> %{user: %{message: %{text: "hi"}}},
...> 1
...> )
%{user: %{id: 42, message: %{text: "hi"}}}

iex> Swiss.Map.deep_merge(
...> %{user: %{id: 42}, messages: [%{id: 1}]},
...> %{user: %{id: 30, age: 40}, messages: [%{id: 2}]}
...> )
%{user: %{id: 30, age: 40}, messages: [%{id: 2}]}

Specs

defaults(map(), map() | keyword()) :: map()

Applies defaults to a map.

Examples

iex> Swiss.Map.defaults(%{a: 42}, %{b: 12})
%{a: 42, b: 12}

iex> Swiss.Map.defaults(%{a: 42}, %{a: 44, b: 12})
%{a: 42, b: 12}

iex> Swiss.Map.defaults(%{a: 42, c: nil}, [a: nil, b: 12, c: 13])
%{a: 42, b: 12, c: nil}

Specs

from_struct(struct() | nil) :: map() | nil

Wrapper around Map.from_struct/1 that tolerates nil.

Examples

iex> Swiss.Map.from_struct(nil)
nil

iex> Swiss.Map.from_struct(%{__struct__: SomeStruct, life: 42})
%{life: 42}

Specs

indif_fetch!(map(), atom()) :: any()

Fetches a value from a map with indifferent access, i.e. given an atom, returns the value that is keyed by that atom, or by its string equivalent.

If both atom and String keys exist in the map, the atom's value is returned.

Examples

iex> Swiss.Map.indif_fetch!(%{life: 42}, :life)
42

iex> Swiss.Map.indif_fetch!(%{"life" => 42}, :life)
42

iex> Swiss.Map.indif_fetch!(%{:life => 42, "life" => 64}, :life)
42

iex> Swiss.Map.indif_fetch!(%{}, :life)
** (KeyError) key :life not found in: %{}
Link to this function

put_if(map, key, value, pred \\ fn v -> !is_nil(v) end)

View Source

Specs

put_if(map(), any(), any(), (any() -> boolean()) | boolean()) :: map()

Runs Map.put/3 only if pred returns truthy when called on the value.

The default behavior is to put unless the value is nil.

pred can also be a boolean.

Examples

iex> Swiss.Map.put_if(%{life: 42}, :life, 22)
%{life: 22}

iex> Swiss.Map.put_if(%{life: 42}, :life, nil)
%{life: 42}

iex> Swiss.Map.put_if(%{life: 42}, :life, nil, &is_nil/1)
%{life: nil}

iex> Swiss.Map.put_if(%{life: 42}, :life, 22, &(&1 < 55))
%{life: 22}

iex> Swiss.Map.put_if(%{life: 42}, :life, 30, true)
%{life: 30}

iex> Swiss.Map.put_if(%{life: 42}, :life, 30, false)
%{life: 42}
Link to this function

put_if_lazy(map, key, value_fn, condition)

View Source

Specs

put_if_lazy(map(), any(), (() -> any()), any()) :: map()

Runs Map.put/3 only if cond is truthy. Unlike Swiss.Map.put_if/4, takes a function that is called when the condition passes, that should return the value to insert in the map.

Examples

iex> Swiss.Map.put_if_lazy(%{life: 42}, :life, fn -> 12 end, true)
%{life: 12}

iex> Swiss.Map.put_if_lazy(%{life: 42}, :life, fn -> 12 end, false)
%{life: 42}

Specs

to_string_keys(map()) :: map()

Converts an atom-keyed map into a string-keyed map.

Examples

iex> Swiss.Map.to_string_keys(%{life: 42})
%{"life" => 42}

iex> Swiss.Map.to_string_keys(%{"life" => 42, death: 27})
%{"life" => 42, "death" => 27}
Link to this function

update_all(map, updater)

View Source

Specs

update_all(map(), ({any(), any()} -> {any(), any()} | any())) :: map()

Appplies an updater function to all keys in the given map.

The updater function receives a {key, value} tuple and may return a new value, or a new {key, value} tuple.

Examples

iex> Swiss.Map.update_all(%{a: 1, b: 2}, &(elem(&1, 1) * 2))
%{a: 2, b: 4}

iex> Swiss.Map.update_all(%{a: 1, b: 2}, &{Atom.to_string(elem(&1, 0)), elem(&1, 1) * 3})
%{"a" => 3, "b" => 6}