View Source Miss.Map (Miss Elixir v0.1.5)
Functions to extend the Elixir Map
module.
Link to this section Summary
Functions
Converts a struct
to map going through all nested structs, different from Map.from_struct/1
that only converts the root struct.
Gets the value for a specific key
in map
.
Renames a single key in the given map
.
Renames keys in the given map
.
Link to this section Types
Specs
Specs
Link to this section Functions
Specs
Converts a struct
to map going through all nested structs, different from Map.from_struct/1
that only converts the root struct.
The optional parameter transform
receives a list of tuples with the struct module and a
function to be called instead of converting to a map. The transforming function will receive the
struct as a single parameter.
If you want to skip the conversion of a nested struct, just pass the atom :skip
instead of a
transformation function.
Date
or Decimal
values are common examples where their map representation could be not so
useful when converted to a map. See the examples for more details.
examples
Examples
# Given the following structs
defmodule Post do
defstruct [:title, :text, :date, :author, comments: []]
end
defmodule Author do
defstruct [:name, :metadata]
end
defmodule Comment do
defstruct [:text]
end
defmodule Metadata do
defstruct [:atom, :boolean, :decimal, :float, :integer, :map]
end
# Convert all nested structs including the Date and Decimal values:
iex> post = %Post{
...> title: "My post",
...> text: "Something really interesting",
...> date: ~D[2010-09-01],
...> author: %Author{
...> name: "Pedro Bonamides",
...> metadata: %Metadata{
...> atom: :my_atom,
...> boolean: true,
...> decimal: Decimal.new("456.78"),
...> float: 987.54,
...> integer: 2_345_678,
...> map: %{key: "value"}
...> }
...> },
...> comments: [
...> %Comment{text: "Comment one"},
...> %Comment{text: "Comment two"}
...> ]
...> }
...> Miss.Map.from_nested_struct(post)
%{
title: "My post",
text: "Something really interesting",
date: %{calendar: Calendar.ISO, day: 1, month: 9, year: 2010},
author: %{
name: "Pedro Bonamides",
metadata: %{
atom: :my_atom,
boolean: true,
decimal: %{coef: 45678, exp: -2, sign: 1},
float: 987.54,
integer: 2_345_678,
map: %{key: "value"}
}
},
comments: [
%{text: "Comment one"},
%{text: "Comment two"}
]
}
# Convert all nested structs skipping the Date values and transforming Decimal values to string:
iex> post = %Post{
...> title: "My post",
...> text: "Something really interesting",
...> date: ~D[2010-09-01],
...> author: %Author{
...> name: "Pedro Bonamides",
...> metadata: %Metadata{
...> atom: :my_atom,
...> boolean: true,
...> decimal: Decimal.new("456.78"),
...> float: 987.54,
...> integer: 2_345_678,
...> map: %{key: "value"}
...> }
...> },
...> comments: [
...> %Comment{text: "Comment one"},
...> %Comment{text: "Comment two"}
...> ]
...> }
...> Miss.Map.from_nested_struct(post, [{Date, :skip}, {Decimal, &to_string/1}])
%{
title: "My post",
text: "Something really interesting",
date: ~D[2010-09-01],
author: %{
name: "Pedro Bonamides",
metadata: %{
atom: :my_atom,
boolean: true,
decimal: "456.78",
float: 987.54,
integer: 2_345_678,
map: %{key: "value"}
}
},
comments: [
%{text: "Comment one"},
%{text: "Comment two"}
]
}
Specs
Gets the value for a specific key
in map
.
If key
is present in map
, the corresponding value is returned. Otherwise, a KeyError
is
raised.
Miss.Map.get!/2
is similar to Map.fetch!/2
but more efficient. Using pattern matching is the
fastest way to access maps. Miss.Map.get!/2
uses pattern matching, but Map.fetch!/2
not.
examples
Examples
iex> Miss.Map.get!(%{a: 1, b: 2}, :a)
1
iex> Miss.Map.get!(%{a: 1, b: 2}, :c)
** (KeyError) key :c not found in: %{a: 1, b: 2}
Specs
Renames a single key in the given map
.
If actual_key
does not exist in map
, it is simply ignored.
If a key is renamed to an existing key, the value of the actual key remains.
examples
Examples
iex> Miss.Map.rename_key(%{a: 1, b: 2, c: 3}, :b, :bbb)
%{a: 1, bbb: 2, c: 3}
iex> Miss.Map.rename_key(%{"a" => 1, "b" => 2, "c" => 3}, "b", "bbb")
%{"a" => 1, "bbb" => 2, "c" => 3}
iex> Miss.Map.rename_key(%{a: 1, b: 2, c: 3}, :z, :zzz)
%{a: 1, b: 2, c: 3}
iex> Miss.Map.rename_key(%{a: 1, b: 2, c: 3}, :a, :c)
%{b: 2, c: 1}
iex> Miss.Map.rename_key(%{a: 1, b: 2, c: 3}, :c, :a)
%{a: 3, b: 2}
Specs
rename_keys(map(), keys_to_rename()) :: map()
Renames keys in the given map
.
Keys to be renamed are given through keys_to_rename
that accepts either:
- a list of two-element tuples:
{actual_key, new_key}
; or - a map where the keys are the actual keys and the values are the new keys:
%{actual_key => new_key}
If keys_to_rename
contains keys that are not in map
, they are simply ignored.
It is not recommended to use Miss.Map.rename_keys/2
to rename keys to existing
keys. But if you do it, after renaming the keys, duplicate keys are removed and the value of the
preceding one prevails. See the examples for more details.
examples
Examples
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, %{a: :aaa, c: :ccc})
%{aaa: 1, b: 2, ccc: 3}
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, a: :aaa, c: :ccc)
%{aaa: 1, b: 2, ccc: 3}
iex> Miss.Map.rename_keys(%{"a" => 1, "b" => 2, "c" => 3}, %{"a" => "aaa", "b" => "bbb"})
%{"aaa" => 1, "bbb" => 2, "c" => 3}
iex> Miss.Map.rename_keys(%{"a" => 1, "b" => 2, "c" => 3}, [{"a", "aaa"}, {"b", "bbb"}])
%{"aaa" => 1, "bbb" => 2, "c" => 3}
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, a: :aaa, z: :zzz)
%{aaa: 1, b: 2, c: 3}
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, a: :c)
%{b: 2, c: 1}
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, c: :a)
%{a: 1, b: 2}
iex> Miss.Map.rename_keys(%{a: 1, b: 2, c: 3}, [])
%{a: 1, b: 2, c: 3}