Here’s my take with plain recursion:
defmodule Converter do
def to_map(input) do
Enum.reduce(input, %{},
fn(%{k: key, v: value}, intermediate_map) ->
merge(intermediate_map, String.split(key, "."), value)
end
)
end
defp merge(map, [leaf], value), do: Map.put(map, leaf, value)
defp merge(map, [node | remaining_keys], value) do
inner_map = merge(Map.get(map, node, %{}), remaining_keys, value)
Map.put(map, node, inner_map)
end
end
Testing it:
[
%{k: "vacancy.state.draft", v: "concept"},
%{k: "vacancy.state.expired", v: "gone"},
%{k: "vacancy.state.online", v: "ready"},
%{k: "vacancy.name", v: "some name"},
%{k: "vacancy.title", v: "jadada"}
]
|> Converter.to_map
|> IO.inspect
produces
%{"vacancy" => %{"name" => "some name",
"state" => %{"draft" => "concept", "expired" => "gone",
"online" => "ready"}, "title" => "jadada"}}
Perhaps it can be done with update_in
and friends, but I didn’t try it