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 :slight_smile:

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