DimWell
How to flatten a map?
Hi,
I am relatively new to Elixir and need a support from more advanced users.
I try to do a simple thing → Flatten Map
But Elixir and functional programming in general is a bit new to me.
I found online a solution, but it looks overcomplicated.
I wonder if maybe there is a solution out of the box provided by the language.
I tried to find something like Map.flatten(%{a: 1, %{b: 2}}) but with no success.
It would be great if you could advice that is the best practice ?
Meanwhile, I found the solution online, please see the code below.
defmodule Json do def flatten(%{} = json) do json |> Map.to_list() |> to_flat_map(%{}) end def flatten(%{} = json) when json == %{}, do: %{} defp to_flat_map([{_k, %{} = v} | t], acc), do: to_flat_map(Map.to_list(v), to_flat_map(t, acc)) 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 end %{id: "1", foo: %{bar: %{qux: "hello world"}, baz: 123}} |> Json.flatten() |> IO.inspect() # %{baz: 123, id: "1", qux: "hello world"}
Currently, due to a lack of knowledge I can’t evaluate this solution.
I would highly appreciate if someone could comment on the above code and mention good and bad points ?
Marked As Solved
benwilson512
Here is a slightly simpler implementation that you may be able to evaluate more easily:
defmodule Foo do
def flatten_map(map) when is_map(map) do
map
|> Map.to_list
|> do_flatten([])
|> Map.new
end
defp do_flatten([], acc), do: acc
defp do_flatten([{_k, v} | rest], acc) when is_map(v) do
v = Map.to_list(v)
flattened_subtree = do_flatten(v, acc)
do_flatten(flattened_subtree ++ rest, acc)
end
defp do_flatten([kv | rest], acc) do
do_flatten(rest, [kv | acc])
end
end
Also Liked
benwilson512
Can you speak a bit about your use case? What do you want to do if sub-maps include the same key as a parent map ie: %{foo: %{bar: 1}, bar: 2}
idi527
You don’t pattern match maps with %{ _k, v }, you do it with %{^k => v}.
Note the pin.







