Toolbox.Utils.Map (toolbox v1.1.0)
A set of utility functions for Maps.
Link to this section Summary
Functions
Creates deep map with value
on key represented by path
. If path
is empty,
it returns given value
.
Deeply updates left
map by right
map. Existing keys from left
map
not contained in right
map are unchanged. New keys from right
map are
added. If the key is present in both maps and both values are maps, maps are
deeply merges. If the key is present in both maps and value of one of them is
not a map, value of key in left
map is replaced by value in right
map.
Removes key represented as path (list of keys) deeply in map if it exists.
Converts map from flat to nested map.
Follows the path
in the (deep) map, defaulting to default
if some of the
objects on the path is missing.
Extracts all (json-like) paths in the map.
Subtracts map from another map, the leaf-paths from the second map are removed from the first.
Converts regular nested map to flat map.
Link to this section Functions
deep_create(list, value)
Creates deep map with value
on key represented by path
. If path
is empty,
it returns given value
.
examples
Examples
iex> Toolbox.Utils.Map.deep_create([], :some_value)
:some_value
iex> Toolbox.Utils.Map.deep_create(["a", :b], :other_value)
%{"a" => %{:b => :other_value}}
deep_merge(left, right)
Deeply updates left
map by right
map. Existing keys from left
map
not contained in right
map are unchanged. New keys from right
map are
added. If the key is present in both maps and both values are maps, maps are
deeply merges. If the key is present in both maps and value of one of them is
not a map, value of key in left
map is replaced by value in right
map.
example
Example
iex> Toolbox.Utils.Map.deep_merge(%{a: 1}, %{b: 2})
%{a: 1, b: 2}
iex> Toolbox.Utils.Map.deep_merge(%{a: %{b: 1}}, %{a: %{c: 3}})
%{a: %{b: 1, c: 3}}
iex> Toolbox.Utils.Map.deep_merge(%{a: %{b: %{c: 1}}}, %{a: %{b: %{d: 2}}})
%{a: %{b: %{c: 1, d: 2}}}
iex> Toolbox.Utils.Map.deep_merge(%{a: 1}, %{a: %{b: 2}})
%{a: %{b: 2}}
iex> Toolbox.Utils.Map.deep_merge(%{a: %{b: 1}}, %{a: 2})
%{a: 2}
iex> Toolbox.Utils.Map.deep_merge(%{a: 1}, %{a: 2})
%{a: 2}
deep_remove(map, path)
Removes key represented as path (list of keys) deeply in map if it exists.
example
Example
iex> Toolbox.Utils.Map.deep_remove(%{a: 1, b: 2}, [])
%{a: 1, b: 2}
iex> Toolbox.Utils.Map.deep_remove(%{a: 1, b: 2}, [:a])
%{b: 2}
iex> Toolbox.Utils.Map.deep_remove(%{a: 1, b: 2}, [:a, :aa])
%{a: 1, b: 2}
iex> Toolbox.Utils.Map.deep_remove(%{a: %{aa: 1, ab: 2}, b: 2}, [:a, :aa])
%{a: %{ab: 2}, b: 2}
iex> Toolbox.Utils.Map.deep_remove(%{a: %{aa: 1, ab: 2}, b: 2}, [:a, :aa, :aaa])
%{a: %{aa: 1, ab: 2}, b: 2}
from_flat_map(flat_map)
Converts map from flat to nested map.
The input map must be flat with array keys, which represent the path to the respective values. The corresponding nested map is then constructed.
Also see to_flat_map/1
which performs the reverse operation.
examples
Examples
iex> Toolbox.Utils.Map.from_flat_map(%{
...> ["contact", "name"] => "Jored",
...> ["contact", "address", "city"] => "Lrno",
...> ["active", "ui"] => true,
...> ["active", "backend"] => false
...> })
%{
"contact" => %{
"name" => "Jored",
"address" => %{
"city" => "Lrno"
}
},
"active" => %{
"ui" => true,
"backend" => false
}
}
iex> Toolbox.Utils.Map.from_flat_map(%{
...> [:very, :very, :very, :very, :very, :very, :deep] => "object",
...> [:very, :very, :very, :very, :very, :very, :nested] => "map"
...> })
%{
very: %{
very: %{
very: %{
very: %{
very: %{
very: %{
deep: "object",
nested: "map"
}
}
}
}
}
}
}
iex> Toolbox.Utils.Map.from_flat_map(%{})
%{}
iex> Toolbox.Utils.Map.from_flat_map(Toolbox.Utils.Map.to_flat_map(%{
...> "contact" => %{
...> "name" => "Jonas",
...> "address" => %{"city" => "Brnp"}},
...> "favorites" => %{
...> "food" => %{
...> 1 => ["cornflakes", "corn"],
...> 5 => ["pizza"],
...> 8 => ["pasta"]
...> }
...> }
...> }
...> ))
%{
"contact" => %{
"name" => "Jonas",
"address" => %{"city" => "Brnp"}},
"favorites" => %{
"food" => %{
1 => ["cornflakes", "corn"],
5 => ["pizza"],
8 => ["pasta"]
}
}
}
get_path(map, path, default \\ nil)
Follows the path
in the (deep) map, defaulting to default
if some of the
objects on the path is missing.
example
Example
iex> object = %{"some" => %{"deep" => %{"object" => "data"}}}
...> Toolbox.Utils.Map.get_path(object, ["some", "deep", "object"])
"data"
iex> Toolbox.Utils.Map.get_path(object, ["non-existent"], "default")
"default"
json_paths(map)
Extracts all (json-like) paths in the map.
Given any artitrarily nested map, the function returns all paths the map contains.
The output is not sorted in a predictable way.
examples
Examples
iex> Toolbox.Utils.Map.json_paths(%{
...> "contact" => %{
...> "name" => "Trest",
...> "phone" => 605554171,
...> "address" => %{"city" => "Brno"}
...> },
...> "active" => false
...> }) |> Enum.sort()
[
["active"],
["contact", "address", "city"],
["contact", "name"],
["contact", "phone"],
]
iex> Toolbox.Utils.Map.json_paths(%{"a" => %{1 => %{%{"cool" => "stuff"} => %{atom: :work_too}}}})
[
["a", 1, %{"cool" => "stuff"}, :atom]
]
iex> Toolbox.Utils.Map.json_paths(%{})
[]
subtract(map, to_delete)
Subtracts map from another map, the leaf-paths from the second map are removed from the first.
examples
Examples
iex> Toolbox.Utils.Map.subtract(%{a: 1, b: 2}, %{a: true})
%{b: 2}
iex> Toolbox.Utils.Map.subtract(%{a: 1}, %{a: %{b: %{c: true}}})
%{a: 1}
iex> Toolbox.Utils.Map.subtract(
...> %{a: %{b: %{c: "1"}, d: "2"}, e: "3"},
...> %{a: %{b: %{c: true}}, e: true}
...> )
%{a: %{b: %{}, d: "2"}}
iex> Toolbox.Utils.Map.subtract(
...> %{"a" => 1, "b" => %{"c" => true}},
...> %{"b" => %{"c" => true}}
...> )
%{"a" => 1, "b" => %{}}
iex> Toolbox.Utils.Map.subtract(%{a: 1, b: 2}, %{c: 2, d: 3})
%{a: 1, b: 2}
iex> Toolbox.Utils.Map.subtract(%{a: %{b: 1}}, %{a: true})
%{}
to_flat_map(map)
Converts regular nested map to flat map.
The input map can be any map - arbitrarily nested, the output is a flat map where keys are arrays representing the path to the respective value.
Also see from_flat_map/1
which performs the reverse operation.
examples
Examples
iex> Toolbox.Utils.Map.to_flat_map(%{
...> "contact" => %{
...> "name" => "Kert",
...> "address" => %{"city" => "Krno"}
...> },
...> "status" => %{"ui" => %{"active" => true},
...> "backend" => %{"fluent" => false}}
...> })
%{
["contact", "name"] => "Kert",
["contact", "address", "city"] => "Krno",
["status", "ui", "active"] => true,
["status", "backend", "fluent"] => false
}
iex> Toolbox.Utils.Map.to_flat_map(%{good: %{1 => :nice}, very: %{deep: %{%{ish: :map} => :askey}}})
%{
[:good, 1] => :nice,
[:very, :deep, %{ish: :map}] => :askey
}
iex> Toolbox.Utils.Map.to_flat_map(%{"regular" => "map"})
%{
["regular"] => "map"
}
iex> Toolbox.Utils.Map.to_flat_map(%{})
%{}