gpt4 book ai didi

Scala 循环选择 : functional looping vs traditional for loop

转载 作者:行者123 更新时间:2023-12-01 07:20:23 24 4
gpt4 key购买 nike

使用函数式构造(map、foreach、flatMap 等)循环遍历集合是否更好?
作为一个虚拟问题,考虑我有一个字符串列表,我想按不同的标准过滤字符串,然后映射它们以获得一些值。
考虑下面的代码:

val x1 = list.filter(criteria1).map(do_something)
val x2 = list.filter(criteria2).map(do_something)

假设我有 5 个这样不同的过滤条件,那么通过这种方式,我将在列表(可能很大)上循环 10 次(一次使用过滤器,一次使用 map )。

但是,我可以将所有这些组合到一个 for 循环中,并在一次迭代中返回/填充 5 个新列表,然后将每个列表映射到总共 6 个循环而不是 10 个循环。
for(i<- 0 to list.length-1){
if(criteria1) //filter
if(criteria2) //filter
}

这段代码可能会迫使我使用可变列表,但严格来说从性能的角度来看,在这种情况下使用函数构造是否有意义。
哪个是更好的方法?

注意:上面的代码/问题只是作为一个例子,我希望它能解释我所指的那种情况

最佳答案

如果你想过滤和映射,你可以使用 withFilter而不是 filter ,这使过滤器变得懒惰,因此您不会多次遍历列表。 for -表达式使用 withFilter为了效率。您也可以查看 view s,它为其他操作提供了类似的惰性。

从您要尝试做什么的问题中并不完全清楚,但我认为您想根据不同的过滤器和映射操作输出 5 个新列表。如果性能至关重要,那么使用您建议的循环和可变构建器是一种合理的方法,这就是编程了多少收集方法(检查源代码)。不知道为什么你认为你需要过滤成 5 个列表,然后遍历每个列表来进行映射 - 为什么不通过将函数应用于每个元素来在构建新列表的同时进行映射?例如

  def split[T](xs: Seq[T])(ops: (T => Boolean, T => T)*): Seq[Seq[T]] = {
val (filters, maps) = ops.unzip
val buffers = IndexedSeq.fill(ops.size)(ListBuffer.empty[T])
for {
x <- xs
i <- buffers.indices
if filters(i)(x)
} buffers(i) += maps(i)(x)
buffers.map(_.toSeq) // return to immutable-land
}

// demo:
val res = split(1 to 10)(
(_ < 5, _ * 100), // multiply everything under 5 by 100
(_ % 2 == 1, 0 - _), // negate all odd numbers
(_ % 3 == 0, _ + 5) // add 5 to numbers divisible by 3
)

println(res)
//Vector(List(100, 200, 300, 400), List(-1, -3, -5, -7, -9), List(8, 11, 14))

我不认为有一个内置的方法来做(我认为)你想做的事情。请注意,如果您使用递归,您可以定义一个没有可变状态的构建器方法,但这曾经是本地可变状态更简洁/可读的地方。

您的问题实际上归结为性能,并且很容易过早优化。如果您确实有真正的性能问题,我建议您只执行上述操作。如果惯用/简单不够好,那么您可以调整一些东西以优化您的特定用例。归结为这样一个事实,即您可能想做的所有事情都没有内置的优化方法。

关于Scala 循环选择 : functional looping vs traditional for loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12084514/

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