Convert map with nested string keys to nested map

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!

2 Likes