Если вы посмотрите API-интерфейс List
с, Set
с, Vector
с, Map
с и т. Д. c, вы увидите множество таких утилит, как: reduce
, fold
, foldLeft
, foldRight
, map
, et c.
Большинство функций предполагает, что вы можете вернуть результат только после обхода всей коллекции. Некоторые процессы обрабатываются только до тех пор, пока не будет выполнено условие, например, .takeWhile(cond)
или не будут приняты только конкретные примеры, которые удовлетворяют условию, например, find(condition)
. Довольно часто случается, что то, что вы пытаетесь сделать с одним l oop, является комбинацией нескольких более простых функций, например:
var index = 0;
var result = 0;
// add all elements until first element bigger than 100
while (index < list.size) {
if (list(index) > 100)
break;
index++;
result += list(index);
}
может быть функционально выражено как:
list.takeWhile(i => i > 100).sum
Способность express к более сложным логикам c улучшится, поскольку вы будете изучать и использовать все больше и больше этих методов. Если вы не возражаете перебирать всю коллекцию, fold
, reduce
и т.п. обычно позволяют вам делать с вашими данными все, что вы хотите.
Однако, если вы все еще не знаете, как что-то реализовать Поскольку вам необходимо, например, отфильтровать, объединить и решить прекратить итерации, чтобы избежать n oop циклов, вы всегда можете вернуться к хвостовому рекурсивному вызову:
@scala.annotation.tailrec // annotation ensured that compiler will optimize body
def myOperation(unprocessedData: List[Int], resultSoFar: Int): Int =
unprocessedData match {
case head :: tail =>
val newResult = resultSoFar + head
myOperation(tail, newResult) // to enable tailrec instead of backtracking
// you pass partial results as argument
// and compiler will rewrite it underneath
// into while with break
case Nil =>
resultSoFar // final result
}
TL; DR
- попробуйте использовать встроенные функции, такие как
.map
, .collect
, .filter
, .drop
, .dropWhile
, .take
, .takeWhile
для построения того, что вам нужно - , если слишком сложно попробуйте использовать
fold
, foldLeft
, foldRight
, reduce
- , если все еще трудно, попробуйте использовать хвостовую рекурсию - это в основном более безопасная версия
while
- break
, поэтому с этим вы всегда сможете реализовать то, что вы хотите