gpt4 book ai didi

scala - 在 scala 中折叠列表的有效方法,同时避免分配和变量

转载 作者:行者123 更新时间:2023-12-03 05:11:56 26 4
gpt4 key购买 nike

我的列表中有一堆项目,我需要分析内容以找出其中有多少是“完整的”。我一开始使用分区,但后来意识到我不需要返回两个列表,所以我切换到折叠:

val counts = groupRows.foldLeft( (0,0) )( (pair, row) => 
if(row.time == 0) (pair._1+1,pair._2)
else (pair._1, pair._2+1)
)

但是我有很多并行用户需要处理很多行,并且它导致了大量的 GC 事件(我的假设......GC可能来自其他的东西,但我怀疑这一点,因为我知道它会在每个折叠的项目上分配一个新的元组)。

暂时,我将其重写为

var complete = 0
var incomplete = 0
list.foreach(row => if(row.time != 0) complete += 1 else incomplete += 1)

修复了 GC,但引入了变量。

我想知道是否有一种方法可以在不使用 vars 的情况下做到这一点,同时也不滥用 GC?

编辑:

对我收到的答案进行严格要求。在大型列表上,var 实现似乎比尾递归优化版本要快得多(比如 40%),后者功能更强大,但应该是等效的。

dhg 的第一个答案似乎与尾递归的性能相当,这意味着大小传递非常高效......事实上,优化后它的运行速度比尾递归稍快 -我的硬件上的递归。

最佳答案

最干净的两遍解决方案可能是只使用内置的 count 方法:

val complete = groupRows.count(_.time == 0)
val counts = (complete, groupRows.size - complete)

但是如果您在迭代器上使用partition,则可以一次性完成此操作:

val (complete, incomplete) = groupRows.iterator.partition(_.time == 0)
val counts = (complete.size, incomplete.size)

这是有效的,因为新返回的迭代器在幕后链接,并且在其中调用 next 将导致它将原始迭代器向前移动,直到找到匹配的元素,但它会记住不匹配的元素另一个迭代器的元素,这样它们就不需要重新计算。

<小时/>

一次性解决方案示例:

scala> val groupRows = List(Row(0), Row(1), Row(1), Row(0), Row(0)).view.map{x => println(x); x}
scala> val (complete, incomplete) = groupRows.iterator.partition(_.time == 0)
Row(0)
Row(1)
complete: Iterator[Row] = non-empty iterator
incomplete: Iterator[Row] = non-empty iterator
scala> val counts = (complete.size, incomplete.size)
Row(1)
Row(0)
Row(0)
counts: (Int, Int) = (3,2)

关于scala - 在 scala 中折叠列表的有效方法,同时避免分配和变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13942106/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com