Can you post some example source data (and possibly the source of create_index_name)? Also, please format your code blocks with triple backticks, right now it’s almost unreadable.
You’ll have to modify part of the code to read the data from a file but otherwise it works. Key insight: use Enum.reduce to accumulate values into a single return value, instead of making a one-keyed map for each parsed line.
defmodule Parse1 do
def data(), do: ~S"""
jhb team names:hawks,maulers,eagles,wolves
dbn team names:sqeaks,bunfighters
"""
def stream_string(text) do
{:ok, io} = StringIO.open(text)
IO.stream(io, :line)
end
def create_index_name(name) do
":" <> String.replace(name, " ", "_")
end
def test() do
# Replace first two lines with your file reading code.
data()
|> stream_string()
|> Stream.map(&String.trim(&1))
|> Stream.map(&String.downcase(&1))
|> Stream.map(&String.split(&1, [":", ","]))
|> Enum.reduce(%{}, fn [head | tail], acc ->
Map.put(acc, create_index_name(head), tail)
end)
end
end
Copy-paste that in iex and then run Parse1.test().
I saw @dimitarvp answered your question already by asking a little bit more about your problem (good technique). Even though you solved the problem a different way, I thought I’d focus on what you asked first: You had an input in a certain shape (list of maps), you wanted an output in a different shape (one map). Here is a possible solution to the input/output problem:
In this case, I wouldn’t even bother with the Stream.map calls. The extra indirection is slowing you down and adding complexity for no real benefit. Thanks to @dimitarvp 's nice sample code, I took it and modified a bit to be more direct.
defmodule Parse2 do
def data(), do: ~S"""
jhb team names:hawks,maulers,eagles,wolves
dbn team names:sqeaks,bunfighters
"""
def stream_string(text) do
{:ok, io} = StringIO.open(text)
IO.stream(io, :line)
end
def create_index_name(name) do
":" <> String.replace(name, " ", "_")
end
def line_to_kv(line) do
[key | names] =
line
|> String.trim()
|> String.downcase()
|> String.split([":", ","])
{create_index_name(key), names}
end
def test2() do
# Replace first two lines with your file reading code.
data()
|> stream_string()
|> Map.new(&line_to_kv/1)
end
end