Если поиск по индексу представляет проблему ( O (n) с List
), вы можете использовать постоянный вектор . Это дает вам O (1) индексирование, а также O (1) обновление. Он также чисто функциональный (неизменный), поэтому жизнь в этом отношении все еще счастлива.
Приложив немного воображения, мы можем преобразовать ваш код напрямую в чисто функциональную версию, используя Vector
:
def filter(numbers: List[Double], size: Int) = {
def walk(numbers: List[Double], buffer: Vector[Double], i: Int): List[Double] = {
numbers match {
case x :: tail => {
val nextBuffer = buffer(i) = x
val nextI = if (i == size) 0 else i + 1
val avg = buffer.foldLeft(0.0) { _ + _ } / size
avg :: walk(tail, nextBuffer, nextI)
}
case Nil => Nil
}
}
walk(numbers, Vector.empty, 0)
}
Обратите внимание, что это не хвостовая рекурсия, поэтому он сломается, когда numbers
будет слишком большим. Это довольно легко решить эту проблему, но я сейчас ленивый.