Reputation: 8461
I have this dataset:
%{
"away" => %{
"id" => "575ec304-wlk3-239n-3032jdns3944",
"points" => 115
},
"home" => %{
"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c",
"points" => 120
}
}
I want to return the map with the most points so that I end up with this.
%{
"home" => %{
"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c",
"points" => 120
}
}
I was thinking the enum.find
would work for this but I haven't had any luck. Any help would be great.
Upvotes: 1
Views: 113
Reputation: 121010
While Enum.max_by/4
might seem a perfect fit here, the most performant solution would be to use plain old good Enum.reduce/3
with guarded clauses.
input = %{ ... }
Enum.reduce(input, nil, fn
{_, %{"points" => pe}}, {_, %{"points" => pa}} = acc when pa > pe -> acc
e, _ -> e
end)
#⇒ {"home", %{"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c", "points" => 120}}
To get back from tuple to map, one might wrap the result with List.wrap/1
and Map.new/1
input
|> Enum.reduce(nil, fn
{_, %{"points" => pe}}, {_, %{"points" => pa}} = acc when pa > pe -> acc
e, _ -> e
end)
|> List.wrap()
|> Map.new()
#⇒ %{"home" => %{"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c", "points" => 120}}
Upvotes: 1
Reputation: 4685
You want to use Enum.max_by/4
for this because you don't need a specific property of the item you're searching for, but instead you want the item itself with the most points.
iex> data = %{
"away" => %{
"id" => "575ec304-wlk3-239n-3032jdns3944",
"points" => 115
},
"home" => %{
"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c",
"points" => 120
}
}
iex> Enum.max_by(data, fn {_, value} -> value["points"] end)
{"home", %{"id" => "583ec7cd-fb46-11e1-82cb-f4ce4684ea4c", "points" => 120}}
Upvotes: 4