[英]How to calculate ratio via akka-stream
查看如何计算 stream 中每个元素的比率(百分比)。
(10,20,30,40,50)->(10/150, 20/150, 30/150, 40/150, 50/150)
150是 stream 中元素的减少总和
图表应将 stream 减少为一个元素,然后将该元素应用于 stream 中的每个元素
我在考虑广播(2)stream,然后在(1)中进行减少(计算总和),(2)应该相同,然后以某种方式使用 zip。 zip 是 1:1 组合的问题。
由于您说数据是有限的(暗示:上游源将完成),因此(在 Scala 中)这样的东西会起作用。
def normalizeToTotal(source: Source[Int, Any]): Source[Double, NotUsed] =
source.map(i => Option(i)) // map everything to Some...
.concat(Source.single(None)) // so we can use None to signal upstream completion
.statefulMapConcat { () =>
var elems: List[Int] = Nil
{ elem: Option[Int] =>
elem.foreach { e => elems = e :: elems } // only when not yet completed
if (elem.isEmpty) {
// upstream is completing (None is the last element)
val des = elems.map(_.toDouble)
val sum = des.sum
val toEmit = des.reverse.map(_ / sum)
elems = Nil // preserve our invariant even in death...
toEmit
} else {
// not yet completed, don't emit
Nil
}
}
}
免责声明:我心中的编译器通过了这一点。
需要注意的是,这将消耗 memory 与 stream 中的元素数量成正比(由于要求在所有元素都已知之前不发射):这不是流式算法,而是对流式 ZDB97442387183ACE14D6 实施的批处理算法.
(再说一次,如果 stream 可以被视为小批量的 stream(我看到你了,Spark ......),批处理同样可以被视为 stream 最常见的是“干”B)
还可以注意到statefulMapConcat
阶段(只要它保持其不变性)将与Option[Int]
s 的无限 stream 一起工作,将None
解释为批处理结束时发出指示符。 当然,如果修改它以使用这样的 stream,在其输入上concat(Source.single(None))
以确保批处理终止可能仍然有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.