Surendra Bharathi
Surendra Bharathi

Reputation: 87

Trying to use Enum.reduce

Trying to convert below template

[
  %{ids: ["A123"], name: "Red"},
  %{ids: ["A123"], name: "Blue"},
  %{ids: ["B123"], name: "Blue"}
]

to

[
  %{ids: ["A123"], name: "Red"},
  %{ids: ["A123", "B123"], name: "Blue"},
]

If the key name is same combine id in one list. For Eg: the name blue has two ids and merged t0 one list. Can anyone help me to achieve this using Enum.reduce

Upvotes: 2

Views: 88

Answers (1)

zwippie
zwippie

Reputation: 15550

data = [
  %{ids: ["A123"], name: "Red"},
  %{ids: ["A123"], name: "Blue"},
  %{ids: ["B123"], name: "Blue"}
]

Using Enum.group_by/3 and List.flatten/1:

data
|> Enum.group_by(&(&1.name), &(&1.ids))
|> Enum.map(fn {color, ids} -> %{name: color, ids: List.flatten(ids)} end)

Using Enum.reduce/3 and Map.update/4:

data
|> Enum.reduce(%{}, fn %{ids: ids, name: name}, acc ->
  Map.update(acc, name, ids, fn prev_ids -> prev_ids ++ ids end)
end)
|> Enum.map(fn {color, ids} -> %{name: color, ids: ids} end)

As you can see using group_by is a little less verbose and possibly more clear. Both approaches use an intermediate map to make grouping easier.

Upvotes: 4

Related Questions