Suggestion on better coding style

I have an list which is like

``````[[1, 5], [3, 12], [4, 10]]
``````

i want to change it to a map like below

``````%{
1 => 5,
3 => 12,
4 => 10
}
``````

Currently i am using following code and my question is , is there a better way to do. i mean if there is more concise way, or may be a built-in function to do so.

``````Enum.reduce([[1, 5], [3, 12], [4, 10]],%{}, fn row, acc ->
acc
|> Map.put(List.first(row), List.last(row))
``````
``````data = [[1, 5], [3, 12], [4, 10]]
Enum.into(data, %{}, fn [a,b] -> {a, b} end)
``````
4 Likes

While Enum.into is the simplest, You could have rewritten your Enum.reduce like this.

``````list = [[1, 5], [3, 12], [4, 10]]
Enum.reduce(list, %{}, fn [k, v], acc -> Map.put(acc, k, v) end)

# or the for version of it

for [k, v] <- list, reduce: %{} do acc -> Map.put(acc, k, v) end
``````
2 Likes

Itâ€™s quite uncommon to use a list of lists like this, a more common approach would be to have the list as a list of binary tuples.

So if you have control over the shape of the incoming list, make it `[{1, 2}, {3, 4}]`, then itâ€™s easy as calling `Map.new(list)`.

Having said that, you can also use `Map.new/2` and `List.to_tuple/1` as this with your initial list shape: `Map.new(list, &List.to_tuple/1)`.

5 Likes

Today I learnt that `for` has a `reduce` option and itâ€™s great !

Thanks

2 Likes

I tried this code that I never saw:

And I have this error:
`** (CompileError) iex:3: unsupported option :reduce given to for`

Its only available since elixir 1.8. You really should update.

1 Like

Itâ€™s true thankâ€™s.

I would not use `Map.put` or `Enum.into` because that means that the runtime copies the map, adds one more pair to it, then throws out the previous one â€“ N times. Thatâ€™s very inefficient.

Go with what @NobbZ suggested: it basically says â€śconstruct a new map using this list and then use this function (the second parameter, in this case `List.to_tuple`) to convert each element of the list to a key/value tupleâ€ť â€“ which is the format that `Map.new` expects.

For (supposedly) even bigger efficiency Iâ€™d write this:

``````Map.new(your_list, fn [k, v] -> {k,v} end)
``````

This has the added benefit that it will break if your list is malformed, namely you want a list of sublists and each of the sublists must be exactly 2 elements long. If thereâ€™s even one sublist that is not 2-sized then youâ€™ll get a runtime error. Annoying, sure, but youâ€™ll know you have a bug very quickly and can fix it.

4 Likes