有一些整数流:
val source = Source(List(1,2,3,4,5))
是否有可能从源获得(count, sum)
结果?对于上面的示例,它将是(5, 15)
。
我想我应该使用流量并将它们组合起来:
val countFlow = Flow[Int].fold(0)((c, _) => c + 1)
val sumFlow = Flow[Int].fold(0)((s, e) => s + e)
如何将上述流量应用于源。或者还有另一种方式吗?
答案 0 :(得分:1)
最终合计
您提供的Flow
对于在消息来源耗尽后获取最终值几乎是正确的:
case class Data(sum : Int = 0, count : Int = 0)
val updateData : (Data, Int) => Data =
(data, i) => Data(data.sum + i, data.count + 1)
val zeroData = Data()
val countAndSum = Flow[Int].fold(zeroData)(updateData)
然后可以将此Flow与Sink.head
组合以获得最终结果:
val result : Future[Data] =
source
.via(countAndSum)
.runWith(Sink[Data].head)
中级值
如果你想要一个“跑步计数器”,例如如果您想要所有中间数据值,则可以使用Flow.scan
代替fold:
val intermediateCountAndSum =
Flow[Int].scan(zeroData)(updateData)
您可以将这些Data
值“排放”到Sink.seq
:
val intermediateResult : Future[Seq[Data]] =
source
.via(intermediateCountAndSum)
.runWith(Sink[Data].seq)
答案 1 :(得分:1)
val graph = Source.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val fanOut = builder.add(Broadcast[Int](2))
val merge = builder.add(Zip[Int, Int])
source ~> fanOut ~> countFlow ~> merge.in0
fanOut ~> sumFlow ~> merge.in1
SourceShape(merge.out)
})
graph.runWith(Sink.last)
答案 2 :(得分:0)
您可以简单地执行以下操作
source.map(list => (list.length, list.reduceLeft(_+_)))
我希望它有用
答案 3 :(得分:0)
case class Stats(sum: Int, count: Int) {
def add(el: Int): Stats = this.copy(sum = sum += el, count = count +=1)
}
object Stats {
def empty: Stats = Stats(0, 0)
}
val countFlow = Flow[Status].fold(Stats.empty)((stats, e) => stats add e)