VR_1
VR_1

Reputation: 153

Filter list of map using Enum.reduce

I have a map as

%Subject
{
    sub_id: 1,
    content: %{
               sub_name: "oracle",
               type: "code",
    },
    publisher: "quantum",
    ouby_id: "afc5a6e23208",
    region: "USA",
  }

I have a list as follows

[
%user{id: 4, name: "kane", status: "A"},
%user{id: 3, name: "Harry", status: "P"},
%user{id: 5, name: "Tom", status: "A"}
]

I want to filter User with status: "A" and create a new map as

[
%{id: 4,name: "kane", sub_id: 1, sub_name: "oracle"},
%{id: 5,name: "Tom", sub_id: 1, sub_name: "oracle"}
]

Can anyone please help me with this?

Thank you.

Upvotes: 0

Views: 1070

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Despite the solution by Adam is perfectly correct, I’d better go with Enum.reduce/3.

[
  %{id: 4, name: "kane", status: "A"},
  %{id: 3, name: "Harry", status: "P"},
  %{id: 5, name: "Tom", status: "A"}
]
|> Enum.reduce([], fn
  %{status: "A"} = elem, acc ->
    elem =
      elem
      |> Map.take(~w|id name|a)
      |> Map.put(:sub_id, subject.sub_id),
      |> Map.put(:sub_name, subject.content.sub_name)
    [elem | acc]
  _, acc ->
    acc
end)
|> Enum.reverse()

Upvotes: 3

Adam Millerchip
Adam Millerchip

Reputation: 23091

I think using a combination of filter and map would be better here. You didn't explain why Subject was necessary, so I just hardcoded the values you said would always be the same.

[
  %User{id: 4, name: "kane", status: "A"},
  %User{id: 3, name: "Harry", status: "P"},
  %User{id: 5, name: "Tom", status: "A"}
]
|> Stream.filter(&(&1.status == "A"))
|> Enum.map(fn map ->
  %{
    id: map.id,
    name: map.name,
    sub_id: 1,
    sub_name: "oracle"
  }
end)

Result:

[
  %{id: 4, name: "kane", sub_id: 1, sub_name: "oracle"},
  %{id: 3, name: "Harry", sub_id: 1, sub_name: "oracle"},
  %{id: 5, name: "Tom", sub_id: 1, sub_name: "oracle"}
]

Upvotes: 2

Related Questions