我有一个CSV文件
revenue,currency,date,random1,random2,random3
1.234,eur,2020-05-19,"random","random","random"
1.234,usd,2020-05-19,"random","random","random"
1.234,eur,2020-05-19,"random","random","random"
1.234,bng,2020-05-19,"random","random","random"
1.234,eur,2020-05-19,"random","random","random"
1.234,eur,2020-05-19,"random","random","random"
1.234,jpy,2020-05-19,"random","random","random"
1.234,cny,2020-05-19,"random","random","random"
1.234,chf,2020-05-19,"random","random","random"
1.234,eur,2020-05-19,"random","random","random"
1.234,eur,2020-05-19,"random","random","random"
上面的只是一个示例,但它可以有许多意想不到的列,前3列是常量,每个CSV都是相同的(头)。
我试图得到这些前3列的地图和其余列的地图列表。
我已经试过了,
"csvs/download.csv"
|> File.stream!()
|> NimbleCSV.RFC4180.parse_stream(skip_headers: false)
|> Stream.transform([], fn r, acc ->
{[Enum.zip(acc, r) |> Enum.into(%{})], acc}
end)
|> Enum.to_list()
这给了我一个空映射列表,
[%{}, %{}, %{}, %{}, %{}, %{}, %{}, %{}, %{}, %{}, %{}, %{}]
我的计划是像这样转换它,然后在一个列表中取前3个,其余的到另一个列表。但是第一部分不起作用。
任何帮助都太好了。解析后的预期结果是
[
%{revenue: revenue, currency: currency, date: date, rest: [%{anyname: any_data, anyname: any_data}]},
%{revenue: revenue, currency: currency, date: date, rest: [%{anyname: any_data, anyname: any_data}]}
....
]
我是这样做的:
data = NimbleCSV.RFC4180.parse_string(File.read("path_to_csv.csv"), skip_headers: false)
known_headers = ~w(revenue currency date)
[headers | content] = data
content
|> Enum.map(fn row ->
headers |> Enum.zip(row) |> Map.new |> Map.split(known_headers)
end)
无法得到预期的结果,但我知道可能有更好的解决方案。
问题是acc
是一个空列表,压缩到空列表会导致每个步骤都是空列表。如果acc
为空,则应该显式地启动它。
"csvs/download.csv"
|> File.stream!()
|> NimbleCSV.RFC4180.parse_stream(skip_headers: false)
|> Stream.transform([], fn
r, [] -> {[], r} # ⇐ THIS
r, acc -> {[acc |> Enum.zip(r) |> Map.new()], acc}
end)
|> Enum.to_list()
对结果进行重组,处理[acc |> Enum.zip(r) |> Map.new()]
部分。例如,分割地图,如问题:
r, acc ->
{result, others} =
acc
|> Enum.zip(r)
|> Map.new()
|> Map.split(~w|revenue currency date|)
{[Map.put(result, :others, others)], acc}