A zipper - это чисто функциональная структура данных с указателем на эту структуру.Другими словами, это элемент с контекстом в некоторой структуре.
Например, библиотека Scalaz предоставляет класс Zipper
, который моделирует список с определенным элементом списка вfocus.
Вы можете получить застежку-молнию для списка, ориентированного на первый элемент.
import scalaz._
import Scalaz._
val z: Option[Zipper[Int]] = List(1,2,3,4).toZipper
Вы можете переместить фокус застежки-молнии с помощью методов, например, на Zipper
Вы можете перейти к следующему смещению от текущего фокуса.
val z2: Option[Zipper[Int]] = z >>= (_.next)
Это похоже на List.tail
за исключением того, что оно запоминает, где оно было.
Затем, как только вы выбрали выбранный элементв фокусе вы можете изменять элементы вокруг фокуса.
val swappedWithNext: Option[Zipper[Int]] =
for (x <- z2;
y <- x.delete)
yield y.insertLeft(x.focus)
Примечание: это с последней ствольной платформой Scalaz, в которой ошибка с хвостовой рекурсивностью методов Zipper find
и move
имеетбыл исправлен.
Метод, который вы хотите, это просто:
def swapWithNext[T](l: List[T], p: T => Boolean) : List[T] = (for {
z <- l.toZipper
y <- z.findZ(p)
x <- y.delete
} yield x.insertLeft(y.focus).toStream.toList) getOrElse l
Это соответствует элементу на основе предиката p
.Но вы можете пойти дальше и рассмотреть все близлежащие элементы.Например, для реализации вставки сортировки.