С намерением изучить и продолжить этот вопрос , мне по-прежнему любопытны идиоматические альтернативы явной рекурсии для алгоритма, который проверяет, упорядочен ли список (или коллекция) . (Я стараюсь упростить здесь задачу, используя оператор для сравнения и тип Int; я хотел бы взглянуть на алгоритм, прежде чем углубляться в его обобщения)
Базовая рекурсивная версия будет (от @Luigi Plinge ):
def isOrdered(l:List[Int]): Boolean = l match {
case Nil => true
case x :: Nil => true
case x :: xs => x <= xs.head && isOrdered(xs)
}
Плохо работающий идиоматический способ:
def isOrdered(l: List[Int]) = l == l.sorted
Альтернативный алгоритм, использующий свертку:
def isOrdered(l: List[Int]) =
l.foldLeft((true, None:Option[Int]))((x,y) =>
(x._1 && x._2.map(_ <= y).getOrElse(true), Some(y)))._1
У него есть недостаток, заключающийся в том, что он будет сравнивать все n элементов списка, даже если он может остановиться раньше после нахождения первого вышедший из строя элемент. Есть ли способ «остановить» фолд и, следовательно, сделать это лучшим решением?
Какие-нибудь другие (элегантные) альтернативы?