如果您正在寻找过滤和映射,您可以使用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))
我不认为有一个内置的方法可以做(我认为)你想做的事情。请注意,如果您使用递归,您可以定义一个没有可变状态的构建器方法,但这曾经是局部可变状态更简洁/可读的地方。
您的问题实际上归结为性能,并且很容易过早优化。如果您确实遇到真正的性能问题,我建议您仅执行上述操作。如果惯用/简单不够好,那么您可能可以调整一些东西以优化您的特定用例。归根结底,您可能想做的所有事情都没有内置的优化方法。