Skip to content

Instantly share code, notes, and snippets.

@sudix
Created January 20, 2017 05:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sudix/51c610078f39265135a3e1e08b442dea to your computer and use it in GitHub Desktop.
Save sudix/51c610078f39265135a3e1e08b442dea to your computer and use it in GitHub Desktop.
Flatten map with nested key on Elixir
defmodule MyMap do
@doc """
flatten given map with nested key.
All keys must be atom or binary.
Returns map
## Examples
iex> XFLAGPayment.Map.flatten_with_parent_key(%{a: 1, b: %{ba: 21, bb: %{bba: 241}}, c: 3})
%{:a => 1, :c => 3, "b.ba" => 21, "b.bb.bba" => 241}
"""
@spec flatten_with_parent_key(map) :: map
def flatten_with_parent_key(map) when is_map(map) do
map
|> Map.to_list()
|> to_flat_map(%{})
end
defp to_flat_map([{pk, %{} = v} | t], acc) do
v |> to_list(pk) |> to_flat_map(to_flat_map(t, acc))
end
defp to_flat_map([{k, v} | t], acc), do: to_flat_map(t, Map.put_new(acc, k, v))
defp to_flat_map([], acc), do: acc
defp to_list(map, pk) when is_atom(pk), do: to_list(map, Atom.to_string(pk))
defp to_list(map, pk) when is_binary(pk), do: Enum.map(map, &update_key(pk, &1))
defp update_key(pk, {k, v} = _val) when is_atom(k), do: update_key(pk, {Atom.to_string(k), v})
defp update_key(pk, {k, v} = _val) when is_binary(k), do: {"#{pk}.#{k}", v}
end
@sudix
Copy link
Author

sudix commented Jan 20, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment