Transform list into nested map

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 :slight_smile:

7 Likes