Current section

Files

Jump to
useful lib useful.ex
Raw

lib/useful.ex

defmodule Useful do
@moduledoc """
A Library of `Useful` functions for building `Elixir` Apps.
"""
@doc """
`atomize_map_keys/1` converts a `Map` with different keys
to a map with just atom keys. Works recursively for nested maps.
Inspired by stackoverflow.com/questions/31990134
## Examples
iex> Useful.atomize_map_keys(%{"name" => "alex", id: 1})
%{id: 1, name: "alex"}
iex> Useful.atomize_map_keys(%{"name" => "alex", data: %{ "age" => 17}})
%{name: "alex", data: %{age: 17}}
"""
def atomize_map_keys(map) when is_map(map) do
for {key, val} <- map, into: %{} do
cond do
is_atom(key) -> {key, atomize_map_keys(val)}
true -> {String.to_atom(key), atomize_map_keys(val)}
end
end
end
def atomize_map_keys(value), do: value
@doc """
`flatten_map/1` flattens a `Map` of any depth
Inspired by: https://stackoverflow.com/questions/39401947/flatten-nested-map
## Examples
iex> map = %{name: "alex", data: %{age: 17, height: 185}}
iex> Useful.flatten_map(map)
%{data__age: 17, data__height: 185, name: "alex"}
"""
def flatten_map(map) when is_map(map) do
map
|> to_list_of_tuples
|> Enum.into(%{})
end
defp to_list_of_tuples(map) do
map
|> Enum.map(&process/1)
|> List.flatten()
end
# avoids ** (Protocol.UndefinedError) protocol Enumerable
# not implemented for ~U[2016-05-24 13:26:08.003Z] of type DateTime
defp process({key, %Date{} = date}), do: return({key, date})
defp process({key, %DateTime{} = datetime}), do: return({key, datetime})
defp process({key, sub_map}) when is_map(sub_map) do
for {sub_key, value} <- flatten_map(sub_map) do
{String.to_atom("#{key}__#{sub_key}"), value}
end
end
defp process({key, value}), do: return({key, value})
# defp process(value), do: value
defp return({key, value}) do
{String.to_atom("#{key}"), value}
end
end