Transforming data from one form to another

Viewed 141

I have the following list:

l = [
        %{id: 1, name: "aash", possess: "car"}, 
        %{id: 1, name: "aash", possess: "bike"}, 
        %{id: 2, name: "rahul", possess: "scooter"}
]

I want to convert this into the following format:

ans = [
        %{id: 1, name: "aash", possess: ["car", "bike"]},
        %{id: 2, name: "rahul", possess: ["scooter"]}
]

Any idea on how to do this in elixir? Since all the variables are immutable, I don't know how to achieve the above transformation.

2 Answers

I'd use Enum.group_by/3 with the mapper function (third argument) returning only the possess field.

[
  %{id: 1, name: "aash", possess: "car"}, 
  %{id: 1, name: "aash", possess: "bike"}, 
  %{id: 2, name: "rahul", possess: "scooter"}
]
|> Enum.group_by(&{&1.id, &1.name}, & &1.possess)
|> Enum.map(fn {{id, name}, possess} ->
  %{id: id, name: name, possess: possess}
end)
|> IO.inspect

Output:

[%{id: 1, name: "aash", possess: ["car", "bike"]},
 %{id: 2, name: "rahul", possess: ["scooter"]}]
l
|> Enum.group_by(fn %{id: id, name: name} -> [id, name] end)
|> Enum.map(fn {[k, v], m} ->
     %{id: k, name: v, possess: Enum.map(m, & &1.possess)}
end)
#⇒ [
#  %{id: 1, name: "aash", possess: ["car", "bike"]},
#  %{id: 2, name: "rahul", possess: ["scooter"]}
# ]

In a case of generic fields the solution would be slightly more complicated, involving Enum.reduce/3 instead of Enum.map/2 on the last step.

Related