To update, I found this question answered by @sasajuric. Modifying the answer to my specific situation I ended up with this, which gives me the result I was looking for.
def to_map(input) do
Enum.reduce(input, %{},
fn({key, value}, intermediate_map) ->
merge(intermediate_map, create_path(key), value)
end)
end
defp create_path(key) do
key
|> String.split(["[", "]"]) # Remove the []
|> Enum.reject(fn x -> x == "" end) # Remove the "" left behind in List
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
When trying other methods, it was the creation of the empty map on keys with other nested values that caused me issues. I was trying to solve the problem by using the Kernel’s put_in
and get_and_update_in
functions which really don’t like nil
values!
Sasa’s solution treats the keys as a list, and generates the inner_map
first. I was trying to do it the other way, using Enum.reduce
and lots of Kernel functions.
Every day’s a school day!