Functions for transforming maps, keys and values.
This module provides recursive map traversal and transformation utilities
including key/value type conversion (atomize, stringify, integerize, floatize),
deep merging, key renaming, and camelCase to snake_case conversion.
The primary public API includes:
deep_map/3- Recursively traverse and transform a map.atomize_keys/2andatomize_values/2- Convert string keys/values to atoms.stringify_keys/2andstringify_values/2- Convert atom keys/values to strings.integerize_keys/2andintegerize_values/2- Convert string keys/values to integers.floatize_keys/2andfloatize_values/2- Convert string keys/values to floats.underscore_keys/2- Convert camelCase string keys to snake_case.rename_keys/4- Rename specific map keys.deep_merge/3- Deep merge two maps.merge_map_list/2- Deep merge a list of maps.delete_in/2- Delete map members by key list.invert/2- Invert a map's keys and values.underscore/1- Convert a camelCase string to snake_case.
Summary
Functions
Transforms a map's String.t keys to atom() keys.
Transforms a map's String.t values to atom() values.
Recursively traverse a map and invoke a function that transforms the map for each key/value pair.
Deep merge two maps.
Delete all members of a map that have a key in the list of keys.
Extract strings from a map or list.
Transforms a map's String.t keys to Float.t keys.
Transforms a map's String.t values to Float.t values.
Returns an argument unchanged.
Transforms a map's String.t keys to Integer.t keys.
Transforms a map's String.t values to Integer.t values.
Invert a map.
Returns the result of deep merging a list of maps.
Prune a potentially deeply nested map of some of its branches.
Removes any leading underscores from map String.t keys.
Rename map keys from from to to.
Transforms a map's atom() keys to String.t keys.
Transforms a map's atom() values to String.t values.
Convert a camelCase string or atom to snake_case.
Convert map String.t keys from camelCase to snake_case.
Functions
Transforms a map's String.t keys to atom() keys.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3. One additional option applies to this function directly::only_existingwhich is set totruewill only convert the binary value to an atom if the atom already exists. The default isfalse.
Returns
- A map with string keys converted to atom keys.
Examples
iex> Localize.Utils.Map.atomize_keys %{"a" => %{"b" => %{1 => "c"}}}
%{a: %{b: %{1 => "c"}}}
Transforms a map's String.t values to atom() values.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3. One additional option applies to this function directly::only_existingwhich is set totruewill only convert the binary value to an atom if the atom already exists. The default isfalse.
Returns
- A map with string values converted to atom values.
Examples
iex> Localize.Utils.Map.atomize_values %{"a" => %{"b" => %{1 => "c"}}}
%{"a" => %{"b" => %{1 => :c}}}
@spec deep_map( map() | list(), function :: function() | {function(), function()}, options :: list() ) :: map() | list()
Recursively traverse a map and invoke a function that transforms the map for each key/value pair.
Arguments
mapis anymap/0.functionis a1-arityfunction or function reference that is called for each key/value pair of the provided map. It can also be a 2-tuple of the form{key_function, value_function}.In the case where
functionis a single function it will be called with the 2-tuple argument{key, value}.In the case where function is of the form
{key_function, value_function}thekey_functionwill be called with the argumentkeyand the value function will be called with the argumentvalue.
optionsis a keyword list of options. The default is[level: 1..1000000, filter: [], reject: [], skip: [], only: [], except: []].
Options
:levelindicates the starting (and optionally ending) levels of the map at which thefunctionis executed. This can be an integer representing onelevelor a range indicating a range of levels. The default is1..1000000.:onlyis a term or list of terms or acheck function. If it is a term or list of terms, thefunctionis only called if thekeyof the map is equal to the term or in the list of terms. If:onlyis acheck functionthen thecheck functionis passed the{k, v}of the current branch in themap. It is expected to return atruthyvalue that iftruesignals that the argumentfunctionwill be executed.:exceptis a term or list of terms or acheck function. If it is a term or list of terms, thefunctionis only called if thekeyof the map is not equal to the term or not in the list of terms. If:exceptis acheck functionthen thecheck functionis passed the{k, v}of the current branch in themap. It is expected to return atruthyvalue that iftruesignals that the argumentfunctionwill not be executed.:filteris a term or list of terms or acheck function. If thekeycurrently being processed equals the term (or is in the list of terms, or thecheck_functionreturns a truthy value) then this branch of the map is processed byfunctionand its output is included in the result.:rejectis a term or list of terms or acheck function. If thekeycurrently being processed equals the term (or is in the list of terms, or thecheck_functionreturns a truthy value) then this branch of the map is omitted from the mapped output.:skipis a term or list of terms or acheck function. If thekeycurrently being processed equals the term (or is in the list of terms, or thecheck_functionreturns a truthy value) then this branch of the map is not processed byfunctionbut it is included in the mapped result.
Notes
:onlyand:exceptoperate on individual keys whereas:filterand:rejectoperate on entire branches of a map.If both the options
:onlyand:exceptare provided then thefunctionis called only when atermmeets both criteria. That means that:excepthas priority over:only.If both the options
:filterand:rejectare provided then:rejecthas priority over:filter.
Returns
- The
maptransformed by the recursive application offunction.
Examples
iex> map = %{a: :a, b: %{c: :c}}
iex> fun = fn
...> {k, v} when is_atom(k) -> {Atom.to_string(k), v}
...> other -> other
...> end
iex> Localize.Utils.Map.deep_map map, fun
%{"a" => :a, "b" => %{"c" => :c}}
iex> map = %{a: :a, b: %{c: :c}}
iex> Localize.Utils.Map.deep_map map, fun, only: :c
%{a: :a, b: %{"c" => :c}}
iex> Localize.Utils.Map.deep_map map, fun, except: [:a, :b]
%{a: :a, b: %{"c" => :c}}
iex> Localize.Utils.Map.deep_map map, fun, level: 2
%{a: :a, b: %{"c" => :c}}
Deep merge two maps.
Arguments
leftis anymap/0.rightis anymap/0.resolveris a 3-arity function used to resolve merge conflicts. The default resolver prefers the right-side value and recursively merges nested maps.
Returns
- A single map that is the deep merge of
leftandright.
Examples
iex> Localize.Utils.Map.deep_merge %{a: "a", b: "b"}, %{c: "c", d: "d"}
%{a: "a", b: "b", c: "c", d: "d"}
iex> Localize.Utils.Map.deep_merge %{a: "a", b: "b"}, %{c: "c", d: "d", a: "aa"}
%{a: "aa", b: "b", c: "c", d: "d"}
Delete all members of a map that have a key in the list of keys.
Arguments
mapis anymap/0or keyword list.keysis a list of keys to delete.
Returns
- The map with all matching keys removed at any depth.
Examples
iex> Localize.Utils.Map.delete_in %{a: "a", b: "b"}, [:a]
%{b: "b"}
Extract strings from a map or list.
Recursively process the map or list and extract string values from maps and string elements from lists.
Arguments
map_or_listis anymap/0or list.optionsis a keyword list of options (currently unused).
Returns
- A flattened list of all string values found in the map or list.
Transforms a map's String.t keys to Float.t keys.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
The map key is converted to a float from
a String.t only when the key is comprised of
a valid float form.
Keys which cannot be converted to a float
are returned unchanged.
Returns
- A map with string keys converted to float keys where possible.
Examples
iex> Localize.Utils.Map.floatize_keys %{a: %{"1.0" => "value"}}
%{a: %{1.0 => "value"}}
iex> Localize.Utils.Map.floatize_keys %{a: %{"1" => "value"}}
%{a: %{1.0 => "value"}}
Transforms a map's String.t values to Float.t values.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
The map value is converted to a float from
a String.t only when the
value is comprised of a valid float form.
Values which cannot be converted to a float
are returned unchanged.
Returns
- A map with string values converted to float values where possible.
Examples
iex> Localize.Utils.Map.floatize_values %{a: %{b: "1.0"}}
%{a: %{b: 1.0}}
iex> Localize.Utils.Map.floatize_values %{a: %{b: "1"}}
%{a: %{b: 1.0}}
Returns an argument unchanged.
Useful when a noop function is required.
Returns
- The argument unchanged.
Examples
iex> Localize.Utils.Map.identity(:anything)
:anything
Transforms a map's String.t keys to Integer.t keys.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
The map key is converted to an integer from
either an atom or String.t only when the
key is comprised of integer digits.
Keys which cannot be converted to an integer
are returned unchanged.
Returns
- A map with string keys converted to integer keys where possible.
Examples
iex> Localize.Utils.Map.integerize_keys %{a: %{"1" => "value"}}
%{a: %{1 => "value"}}
Transforms a map's String.t values to Integer.t values.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
The map value is converted to an integer from
either an atom or String.t only when the
value is comprised of integer digits.
Values which cannot be converted to an integer are returned unchanged.
Returns
- A map with string values converted to integer values where possible.
Examples
iex> Localize.Utils.Map.integerize_values %{a: %{b: "1"}}
%{a: %{b: 1}}
Invert a map.
Requires that the map is a simple map of keys and a list of values or a single non-map value.
Arguments
mapis anymap/0.optionsis a keyword list of options.
Options
:duplicateswhich determines how duplicate values are handled:nilorfalsewhich is the default and means only one value is kept.Map.new/1is used meaning the selected value is non-deterministic.:keepmeaning duplicate values are returned in a list.:shortestmeans the shortest duplicate is kept. This operates on string or atom values.:longestmeans the longest duplicate is kept. This operates on string or atom values.
Returns
- A map with keys and values swapped.
Returns the result of deep merging a list of maps.
Arguments
listis a list of maps to be merged.resolveris a 3-arity function used to resolve merge conflicts. The default resolver prefers the right-side value and recursively merges nested maps.
Returns
- A single map that is the result of deep merging all maps in the list.
Examples
iex> Localize.Utils.Map.merge_map_list [%{a: "a", b: "b"}, %{c: "c", d: "d"}]
%{a: "a", b: "b", c: "c", d: "d"}
Prune a potentially deeply nested map of some of its branches.
Arguments
mapis anymap/0.funis a 1-arity function. Branches for which the function returns a truthy value are removed from the map.
Returns
- The map with matching branches pruned.
Removes any leading underscores from map String.t keys.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
Returns
- A map with leading underscores removed from string keys.
Examples
iex> Localize.Utils.Map.remove_leading_underscores %{"a" => %{"_b" => "b"}}
%{"a" => %{"b" => "b"}}
Rename map keys from from to to.
Arguments
mapis anymap/0.fromis any value map key.tois any valid map key.optionsis a keyword list of options passed todeep_map/3.
Returns
- A map with keys matching
fromrenamed toto.
Examples
iex> Localize.Utils.Map.rename_keys %{"a" => %{"this_one" => "value"}}, "this_one", "that_one"
%{"a" => %{"that_one" => "value"}}
Transforms a map's atom() keys to String.t keys.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
Returns
- A map with atom keys converted to string keys.
Examples
iex> Localize.Utils.Map.stringify_keys %{a: %{"1" => "value"}}
%{"a" => %{"1" => "value"}}
Transforms a map's atom() values to String.t values.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
Returns
- A map with atom values converted to string values.
Examples
iex> Localize.Utils.Map.stringify_values %{a: %{"1" => :value}}
%{a: %{"1" => "value"}}
Convert a camelCase string or atom to snake_case.
This is the code of Macro.underscore/1 with modifications.
The change is to cater for strings in the format This_That
which in Macro.underscore/1 gets formatted as this__that
(note the double underscore) when we actually want this_that.
Arguments
stringis aString.toratom()to be transformed.
Returns
- A snake_case
String.t.
Examples
iex> Localize.Utils.Map.underscore "thisThat"
"this_that"
iex> Localize.Utils.Map.underscore "This_That"
"this_that"
Convert map String.t keys from camelCase to snake_case.
Arguments
mapis anymap/0.optionsis a keyword list of options passed todeep_map/3.
Returns
- A map with camelCase string keys converted to snake_case.
Examples
iex> Localize.Utils.Map.underscore_keys %{"a" => %{"thisOne" => "value"}}
%{"a" => %{"this_one" => "value"}}