# How to merge list pares into a single Map?

I have a list like this.

``````[ ["key1", 1], ["key2", 2], ["key3", 3] ]
``````

Is there any way to convert the list into a single map like this?

``````%{key1: 1, key2: 2, key3: 3}
``````
1 Like

A for comprehension works nicely here:

``````list = [ ["key1", 1], ["key2", 2], ["key3", 3] ]
for [k, v] <- list, into: %{}, do: { String.to_atom(k), v }``````
2 Likes

And also âclassicâ approach:

``````list |> Stream.map(fn [k, v] -> { String.to_atom(k), v} end) |> Enum.into(%{})
``````

In this case comprehension is awesome, because itâs really concise and readable.

2 Likes

Depending of the source of the strings, Iâd prefer to use `String.to_existing_atom/1` to not waste strictly limited ressources.

5 Likes

Thank you for the quick replies!
I can convert it as I expected!

BTW, as the list was filtered with Enum.filter/2 beforehand, I donât have to worry to waste the Atom tables, in fact.

2 Likes

An important difference between the solutions that @amarraja and @PatNowak presented, is that the Enum.map + Enum.into combination creates an intermediate list, while the for-comprehension does not.

3 Likes

I could use Stream

1 Like

That would not resolve the problem, only delay it:

``````list_of_kv_lists
|> Enum.map(fn [k, v] -> { String.to_existing_atom(k), v} end)
|> Enum.into(%{})
``````

would first transform
`[ ["key1", 1], ["key2", 2], ["key3", 3] ]` into
`[ {:key1, 1}, {:key2, 2}, {:key3, 3}]` and this then into
`%{key1: 1, key2: 2, key3: 3}`.

``````list_of_kv_lists
|> Stream.map(fn [k, v] -> { String.to_existing_atom(k), v} end)
|> Stream.into(%{})
|> Stream.run
``````

would not do anything until `Stream.run` is reached, and then take the first element [âkey1â, 1], transform it into {:key1, 1}, insert this into the map, take the second element [âkey2â, 2], transform it into {:key2, 2}, insert this into the map, etc.
This transformation step thus still is done separately.

If you want to do it âat onceâ, you can either use a for-comprehension or use the three-argument version of `Enum.into`:

``````list_of_kv_lists
|> Enum.into(%{}, fn [k, v] ->  { String.to_existing_atom(k), v} end)
``````
1 Like

Why not use simply `Stream.map` and `Enum.into`? I updated my answer above.

2 Likes

Because this would mean that you add the extra overhead of working with Streams for no extra purpose. If you want to be sure you can benchmark, but I am fairly certain that in this simple example, the version that does not use streams is significantly faster.

1 Like

This would be the âclassicâ approach Iâd use. ^.^

``````iex> list = [ ["key1", 1], ["key2", 2], ["key3", 3] ]
[["key1", 1], ["key2", 2], ["key3", 3]]

iex> list |> Enum.reduce(%{}, fn ([k,v],acc) -> Map.put(acc,String.to_existing_atom(k),v) end) %{key1: 1, key2: 2, key3: 3}
``````

And no intermediate list, no stream overhead, etcâŠ ^.^

1 Like