在Stream.take之后使用剩余的流(1)

时间:2016-02-21 11:54:55

标签: elixir

我正在使用库来读取返回行流的csv文件:

File.stream!("some_file.csv")
|> CSV.decode  # returns a stream of rows

第一行通常是csv标题,所以我认为分割标题和正文会很酷:

def split_header_and_body(row_stream) do
  header = row_stream |> Stream.take(1) |> Enum.to_list |> List.first
  body = row_stream |> Stream.drop(1)

  {header, body}
end

这不起作用,可能是因为Stream.take/1结束了枚举(如文档中所述)。

我认为一切都是不可变的,所以我可以重用初始row_stream,但事实并非如此,我也无法找到如何复制流。

2 个答案:

答案 0 :(得分:0)

这应该可以正常工作。我认为问题在于你想在返回之前调用身上的Enum.to_list,否则你将返回一个Stream,这可能不是你想要的。

Stream本身是不可变的。事实上,你可以做到

row_stream | > Stream.take(1) |> Enum.to_list |> IO.inspect

立即致电

row_stream | > Stream.take(5) |> Enum.to_list |> IO.inspect

你会看到这个的真相。

答案 1 :(得分:0)

我不理解您为什么说“它不起作用”。我已经尝试过您的代码,并且可以正常工作。

事实上,流是不可变的,在文档中说

懒惰地从可枚举中获取下一个计数元素并停止枚举

意味着生成的流已停止,而不是原始流保持不变

无论如何,我已经完成了另一个版本的代码,我认为它更简单

def split_header_and_body(row_stream) do
  {Enum.at(row_stream,0), Stream.drop(row_stream,1)}
end