1

I'm doing doing "map" over a collection and getting back a list of maps:

 res1 = Enum.map(my_collection, fn a -> %{a.id => get_some_data(a)} end) # => [%{1 => 123}, %{2 => 456}] 

How can I flatten the list of maps - res1 - so that I have this:

%{1 => 123, 2 => 456} 

2 Answers 2

4

While both Enum.map/2 and Kernel.SpecialForms.for/1 perfectly do their job, there is also a possibility to achieve the same result with Enum.reduce/3:

iex|1 ▶ input = [%{id: 1, data: :foo}, %{id: 2, data: :bar}] #⇒ [%{data: :foo, id: 1}, %{data: :bar, id: 2}] iex|2 ▶ Enum.reduce(input, %{}, fn e, acc -> ...|2 ▷ Map.put(acc, e.id, e.data) ...|2 ▷ end) #⇒ %{1 => :foo, 2 => :bar} 
Sign up to request clarification or add additional context in comments.

Comments

3

Easiest thing here would be to construct a Keyword list during the map:

coll |> Enum.map(fn a -> {a.id, get_some_data(a)} end) |> Map.new 

Or:

for a <- coll, id = a.id, data = get_some_data(a), into: %{} do {id, data} end 

The problem was that you were building a map on each iteration, rather than building a key/value pair, which is what Keyword lists/maps are made of.

2 Comments

Enum.map_reduce won't help?
It's just not necessary is all - you get the Keyword list for free by building a list of tuples, which Map.new can convert from, and using for the list construction is skipped entirely and the map is built directly, so that approach is more optimal.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.