我有200万个数据文件要处理。 以下代码需要2个小时才能完成。
out_file = "./output.tsv"
result = "./input.tsv"
|> File.stream!
|> CSV.decode(separator: ?\t, headers: headers)
|> Enum.map(&(elem(&1, 1)))
|> Enum.group_by(&{&1.id, &1.name})
|> Enum.map(&(format_data(&1)))
File.write(out_file, result)
为了获得更高的性能,我使用了Flow
,然后编写了以下代码。
好像是Enum
,所以我只添加了Flow.from_enumerable
,然后将Enum
重新写入了Flow
。
out_file = "./output.tsv"
result = "./input.tsv"
|> File.stream!
|> CSV.decode(separator: ?\t, headers: headers)
|> Flow.from_enumerable(stages: 4)
|> Flow.map(&(elem(&1, 1)))
|> Flow.group_by(&{&1.id, &1.name})
|> Flow.map(&(format_data(&1)))
File.write(out_file, result)
它不起作用。我认为使用Flow
这样的方式不正确。
请让我知道您的建议,以正确使用Flow
。
答案 0 :(得分:1)
Flow
主文档页面上最上面的示例显示,您必须终止Flow
以及Stream
并使用类似Enum.to_list()
的名称。
在您的第一个摘录中,终止发生在第一次调用Enum.map/2
(Stream.map/2
时,并且family将用于流处理,File.stream!/1
的作用与{{1} },因为您立即将其终止。)
此外,NimbleCSV
由Elixir核心团队明确创建,用于流处理CSV。无论如何,下面的方法可能会起作用:
Fire.read/1
更好的方法是:
result =
"./input.tsv"
|> File.stream!
# here the stream is terminated
|> CSV.decode(separator: ?\t, headers: headers)
|> Flow.from_enumerable(stages: 4)
|> Flow.map(&(elem(&1, 1)))
|> Flow.group_by(&{&1.id, &1.name})
|> Flow.map(&(format_data(&1)))
# ⇓ THIS IS IMPORTANT
|> Enum.to_list()