1
\$\begingroup\$

Consider the list of string values,

lines = ["foo: 1", "bar: 2", "baz: 3"]

That one might transform into the Elixir map,

%{ "foo": "1", "bar": "2", "baz": "3"}

using a simple Enum.reduce,

Enum.reduce(lines, %{}, fn(line, result) ->
 [key, value] = String.split(line, ": ")
 Map.put(result, key, value)
end)

How might one refactor this into something more succinct, specifically with the third argument passed to reduce? For example, my instinct wants to do something like,

Enum.reduce(lines, %{}, fn(line, result) ->
 String.split(line, ": ") |> Map.put(result)
end)

but the Elixir pipe operator doesn't allow piping multiple values nor piping them to anything other than the first argument.

asked Jun 14, 2017 at 18:27
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

You can do this with an anonymous function

Enum.reduce(lines, %{}, fn(line, result) ->
 String.split(line, ": ")
 |> (fn(x) -> Map.put(result, hd(x), List.last(x)) end).()
end)

You can also do it like this

Enum.reduce(lines, [], fn(line, result) -> result ++ String.split(line, ": ") end)
 |> Enum.chunk(2)
 |> Map.new(fn [k, v] -> {k, v} end)

which I less efficient, because it does 2 iterations, but I think it looks cleaner.

answered Jun 30, 2017 at 16:06
\$\endgroup\$
2
\$\begingroup\$

This would also be solvable with a map instead of a reduce

lines
|> Enum.map(&String.split(&1, ": "))
|> Map.new(&List.to_tuple/1)
answered Aug 25, 2017 at 1:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.