Assuming all maps in the list will have same keys and the list of maps being x
and map of lists being y
:
You can convert x
to y
with-
x
|> Enum.reduce(%{}, fn x, acc -> Map.merge(x, acc, fn _, a, b -> is_list(b) && [a | b] || [a | [b]] end) end)
|> Map.map(fn {_, value} -> Enum.reverse(value) end)
and you can convert y
to x
with-
{k,vs} = y |> then(&{Map.keys(&1), Map.values(&1) |> Enum.zip()})
Enum.reduce(vs, [], fn x, acc -> [Map.new(Enum.zip(k, Tuple.to_list(x))) | acc] end)
I did it in a hurry so I could be wrong, but in general, reduce is your friend in cases like these 
Edit:
What if your list was: [%{x: 0, y: 0, z: 0}, %{x, 0, y: 0}, %{z: 0}, %{p: 10, q: 10}]
? How would you like the solutions to be then? In the solution I gave above, it would work best if you have uniform data structure. But with some tweak at the reverse
function (i.e. maybe Map.map(fn {_, value} -> is_list(value) && Enum.reverse(value) || [value] end)
) you could achieve the desired result but the inverse of it could need some more love. Let me know if you can get something around those?
Maybe there are some more appropriate Enum.*
function out there that could do it faster but this is (or something around this) how I worked on transforming CSV file at work long ago (your vice-versa part).
Also, I really, really wish iex
had multiline history enabled 