Hello I'm a beginner in Elixir and I want to parse and stock a CSV file in an Elixir object.
But it's display that:
** (FunctionClauseError) no function clause matching in anonymous fn/1 in The following arguments were given to anonymous fn/1 in # 1 ["41", "5", "59", "N", "80", "39", "0", "W", "Youngstown", "OH"] anonymous fn/1 in (elixir 1.10.3) lib/stream.ex:482: anonymous fn/4 in (elixir 1.10.3) lib/stream.ex:1449: Stream.do_element_resource/6 (elixir 1.10.3) lib/stream.ex:1609: Enumerable.Stream.do_each/4 (elixir 1.10.3) lib/enum.ex:959: (mix 1.10.3) lib/mix/task.ex:330: Mix.Task.run_task/3 (mix 1.10.3) lib/mix/cli.ex:82: Mix.CLI.run_task/2Here my code:
defmodule Siren do def parseCSV do IO.puts("Let's parse CSV file...") File.stream!("../name.csv") |> Stream.map(&String.trim(&1)) |> Stream.map(&String.split(&1, ",")) |> Stream.filter(fn ["LatD" | _] -> false end) |> Enum.find(fn State -> String [LatD, LatM, LatS, NS, LonD, LonM, LonS, EW, City, State] -> IO.puts("find -> #{State}") true end) end
endAnd the csv file:
LatD,LatM,LatS,NS,LonD,LonM,LonS,EW,City,State
41,5,59,N,80,39,0,W,Youngstown,OH
42,52,48,N,97,23,23,W,Yankton,SD
46,35,59,N,120,30,36,W,Yakima,WA
42,16,12,N,71,48,0,W,Worcester,MA
43,37,48,N,89,46,11,W,WisconsinDells,WI
36,5,59,N,80,15,0,W,Winston-Salem,NC
49,52,48,N,97,9,0,W,Winnipeg,MB
39,11,23,N,78,9,36,W,Winchester,VA
34,14,24,N,77,55,11,W,Wilmington,NC
39,45,0,N,75,33,0,W,Wilmington,DE
48,9,0,N,103,37,12,W,Williston,ND
41,15,0,N,77,0,0,W,Williamsport,PA
37,40,48,N,82,16,47,W,Williamson,WV
33,54,0,N,98,29,23,W,WichitaFalls,TX
37,41,23,N,97,20,23,W,Wichita,KS
40,4,11,N,80,43,12,W,Wheeling,WV
26,43,11,N,80,3,0,W,WestPalmBeach,FL
47,25,11,N,120,19,11,W,Wenatchee,WA
41,25,11,N,122,23,23,W,Weed,CA 2 Answers
The first issue is here:
|> Stream.filter(fn ["LatD" | _] -> false
end)all the lines should pass this and the only first one matches the given clauses. This would fix the issue
|> Stream.filter(fn ["LatD" | _] -> false _ -> true
end)or
|> Stream.reject(&match?(["LatD" | _], &1))Enum.find(fn State -> String after looks unclear and would be surely the next issue. I failed to understand what have you tried to achieve here.
The general advice would be: don’t reinvent the wheel and use NimbleCSV written by José Valim to parse CSVs, because there are lot of corner cases (like commas inside quotes in any field etc,) handled properly in the aforementioned library.
Aleksei Matiushkin gave you the right answer but also you have this function:
fn State -> String [LatD, LatM, LatS, NS, LonD, LonM, LonS, EW, City, State] -> IO.puts("find -> #{State}") true
endIt accepts two possible values, either State which is an atom, or a list of 10 specific atoms.
What you want to do is use variables, and variables in Elixir start with a lowercase letter or an underscore if it has to be ignored.
fn state -> String [latd, latm, lats, ns, lond, lonm, lons, ew, city, state] -> IO.puts("find -> #{state}") true
endBut in this case, the first clause of the function will always match anything because it acts like a catch-all clause.
What you probably want is:
fn [_latd, _latm, _lats, _ns, _lond, _lonm, _lons, _ew, _city, state] -> IO.puts("find -> #{state}") # here decide if you want to return true or false, # for instance `state == NC` true
end 1