Начиная с Scala 2.13
, List
теперь поставляется с компоновщиком unfold
, который можно комбинировать с String::span
:
List.unfold("aaaabbaaacdeeffg") {
case "" => None
case rest => Some(rest.span(_ == rest.head))
}
// List[String] = List("aaaa", "bb", "aaa", "c", "d", "ee", "ff", "g")
или, в качестве альтернативы, в сочетании с Scala 2.13
Option#unless
строитель:
List.unfold("aaaabbaaacdeeffg") {
rest => Option.unless(rest.isEmpty)(rest.span(_ == rest.head))
}
// List[String] = List("aaaa", "bb", "aaa", "c", "d", "ee", "ff", "g")
подробности:
- Развернуть (
def unfold[A, S](init: S)(f: (S) ⇒ Option[(A, S)]): List[A]
) основано на внутреннем состоянии (init
), которое в нашем случае инициализируется с "aaaabbaaacdeeffg"
.
- Для каждой итерации мы
span
(def span(p: (Char) ⇒ Boolean): (String, String)
) это внутреннее состояние, чтобы найти префикс, содержащий тот же символ, и создать кортеж (String, String)
, который содержит префикс и остальную часть строки. span
очень удачно в этом контексте, поскольку он производит именно то, что ожидает unfold
: кортеж, содержащий следующий элемент списка и новое внутреннее состояние.
- Развертывание прекращается, когда внутреннее состояние равно
""
, и в этом случае мы производим None
, как и ожидалось при развертывании для выхода.