Created
October 7, 2016 21:39
-
-
Save eborden/4c9519dedecb93f5789b9c0fba437d5e to your computer and use it in GitHub Desktop.
Naive CSV parser in Elixir
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule CSV do | |
defp linesTransform(str, acc) do | |
case String.split(str, ~r/\n|\r\n/) do | |
[] -> {:halt, acc} | |
[head] -> {[], acc <> head} | |
[head | tail] -> | |
interspersedLines = Enum.take(tail, Enum.count(tail) - 1) | |
{[acc <> head] ++ interspersedLines, List.last tail} | |
end | |
end | |
defp lines(enum) do | |
Stream.transform(enum, "", &linesTransform(&1, &2)) | |
end | |
defp split(enum, delim) do | |
Stream.map(enum, &String.split(&1, delim)) | |
end | |
def parse(enum, args) do | |
delimiter = Keyword.get(args, :delimiter, ",") | |
with_head = Keyword.get(args, :with_head, false) | |
lined = lines(enum) | |
if with_head do | |
headers = Stream.take(lined, 1) | |
|> split(delimiter) | |
|> Stream.concat | |
|> Enum.map(&String.to_atom &1) | |
lined |> Stream.drop(1) | |
|> split(delimiter) | |
|> Stream.map(&List.zip([headers, &1])) | |
|> Stream.map(&Enum.into(&1, %{})) | |
else | |
lined |> split(delimiter) | |
end | |
end | |
end | |
IO.puts "With Header Parsing" | |
File.stream!("foo.csv", [:utf8], 1024) | |
|> CSV.parse(delimiter: ",", with_head: true) | |
|> Stream.take(1) | |
|> Enum.each(&IO.puts(&1[:Email])) | |
IO.puts "" | |
IO.puts "Without Header Parsing" | |
File.stream!("foo.csv", [:utf8], 1024) | |
|> CSV.parse(delimiter: ",") | |
|> Stream.take(2) | |
|> Enum.each(&Enum.at(&1, 1) |> IO.puts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment