是否可以在 Elixir 中的流上运行reduce?

问题描述 投票:0回答:2

是否可以减少 Elixir 中的流?

我看到 Stream.scan 但它不返回累加器。

file_stream
|> Stream.each(&parse_line/1)
|> Enum.reduce(&reduce_fn/2)

我似乎遇到了以下问题,但想知道是否可以这样做?

elixir
2个回答
7
投票

减少流量是没有意义的。

Enum
模块与
Stream
中的函数之间的核心区别是,前者是贪婪的,而后者是懒惰的。

也就是说,

Stream
产生一组转换,可以在每个集合的元素基础上延迟应用,传递。

但是

reduce
(又名
foldl
)已经是一种有效的贪心操作,如果不遍历整个集合就无法得到结果。 (顺便说一句,这就是为什么
Stream.scan/3
不返回累积值的原因。)


枚举

#  ===== code =====        ===== piped through =====
[1, 2, 3]                        # [1, 2, 3]
#                                #     ⇓
|> Enum.map(&IO.inspect/1)       # [1, 2, 3]
#                                #     ⇓
|> Enum.map(&IO.inspect/1)       # [1, 2, 3]

#⇒ 1 2 3 1 2 3

直播

#  ===== code =====        ===== piped through =====
[1, 2, 3]                        # 1  2  3
#                                # ⇓  ⇓  ⇓
|> Stream.map(&IO.inspect/1)     # 1  2  3
#                                # ⇓  ⇓  ⇓
|> Stream.map(&IO.inspect/1)     # 1  2  3
|> Enum.to_list()                # termination!
#                                # ⇒  ⇒  ⇒

#⇒ 1 1 2 2 3 3

0
投票

如果您想积累一些价值,您可能会寻找

Stream.transform/3
Stream.transform/4
Stream.transform/5
。这将允许您保留一个累加器,这通常就是人们会在枚举器上进行归约的原因。

例如,文档显示了如何通过以下方式实现 Stream.take(enum, n):

enum = 1001..9999
n = 3
stream = Stream.transform(enum, 0, fn i, acc ->
  if acc < n, do: {[i], acc + 1}, else: {:halt, acc}
end)

Enum.to_list(stream)
[1001, 1002, 1003]

更多信息:https://hexdocs.pm/elixir/1.12.3/Stream.html#transform/3

© www.soinside.com 2019 - 2024. All rights reserved.