View Source Toolbox.Utils.Map (toolbox v5.5.0)
A set of utility functions for maps.
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.
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.
Functions
Creates deep map with value on key represented by path. If path is empty,
it returns given value.
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}}
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
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}
Removes key represented as path (list of keys) deeply in map if it exists.
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}
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
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"]
}
}
}
Follows the path in the (deep) map, defaulting to default if some of the
objects on the path is missing.
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"
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
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(%{})
[]
Subtracts map from another map, the leaf-paths from the second map are removed from the first.
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})
%{}
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
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(%{})
%{}