billposters
Enum.reduce for idiots
I have a list of maps that provide a type of property lookup, and a map with values.
lookup =
[
%{key: "foo", type: :string},
%{key: "bar", type: :string},
%{key: "baz", type: :string}
]
params = %{foo: "bananas", baz: "apples}
What I’ve been attempting to do (unsuccessfully) is to use Enum.reduce, for lack of a better approach, in order to combine the two into the following format, while discarding any lookup keys that aren’t present in values:
output =
[
%{key: :foo, value: "bananas", type: :string},
%{key: :baz, value: "apples", type: :string},
]
I had tried this, but I can’t work out how to access the value from params using the atom key from lookup.
def clever_merge(lookup, params) do
Enum.reduce(lookup, [], fn(%{key: k, type: t}, output) ->
with rec <- %{key: String.to_atom(k), value: params.k, type: t} do
List.insert_at(output, -1, rec)
end
end)
end
The other issue is filtering out keys that aren’t present in params. I tried a few combinations of if statements around Enum.reduce but I couldn’t work it out.
I know it’s always a big ask but could someone point me in the right direction please?
Thanks.
Marked As Solved
brettbeatty
I would actually swap the roles of your lookup and params variables. If order doesn’t matter, you could just turn lookup into a map and iterate over params to create your expected output.
lookup = [
%{key: "foo", type: :string},
%{key: "bar", type: :string},
%{key: "baz", type: :string}
]
lookup = Map.new(lookup, &{&1.key, &1.type})
#=> %{"bar" => :string, "baz" => :string, "foo" => :string}
for {key, value} <- params,
{:ok, type} = Map.fetch(lookup, to_string(key)) do
%{key: key, value: value, type: type}
end
Also Liked
ityonemo
I think you shouldn’t use Enum.reduce for this. Enum.flat_map is better, since you are going from list to list and possibly omitting some.
lookup = [
%{key: "foo", type: :string},
%{key: "bar", type: :string},
%{key: "baz", type: :string}
]
params = %{"foo" => "bananas", "baz" => "apples"}
Enum.flat_map(lookup, fn
map when is_map_key(params, :erlang.map_get(:key, map)) ->
[Map.put(map, :value, params[map.key])]
_ -> []
end)
billposters
Thanks for everybody’s help. I hadn’t thought of swapping roles and looping over the params.
But it was great to learn from all the different takes on using Enum. It’s been a real benefit, so thank you.
iangl
The answer above is very straightforward and I think should work pretty well!
If you do wanna go with reducing because the order matters, I think this should work:
Enum.reduce(lookup, [], fn %{key: key} = map, acc ->
if Map.has_key?(params, key) do
value = params[key]
acc ++ [Map.put(map, :value, value)]
else
acc
end
end)
Have not tested it, but I’d believe it will work
Last Post!
billposters
Thanks for everybody’s help. I hadn’t thought of swapping roles and looping over the params.
But it was great to learn from all the different takes on using Enum. It’s been a real benefit, so thank you.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









