billposters

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

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

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

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

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

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.

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New

Other popular topics Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31525 112
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New