Учитывая, например:
List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
Я бы хотел:
List(List(5), List(2), List(3, 3, 3), List(5, 5), List(3, 3), List(2, 2, 2))
Я бы предположил, что есть простая функция List, которая делает это, но я не могу ее найти.
Учитывая, например:
List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
Я бы хотел:
List(List(5), List(2), List(3, 3, 3), List(5, 5), List(3, 3), List(2, 2, 2))
Я бы предположил, что есть простая функция List, которая делает это, но я не могу ее найти.
Это трюк, который я обычно использую:
def split[T](list: List[T]) : List[List[T]] = list match {
  case Nil => Nil
  case h::t => val segment = list takeWhile {h ==}
    segment :: split(list drop segment.length)
}
На самом деле... Это не так, я обычно реферат над типом коллекции и оптимизируюсь с помощью хвостовой рекурсии, но хочу сохранить ответ простым.
val xs = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
Здесь другой путь.
(List(xs.take(1)) /: xs.tail)((l,r) =>
  if (l.head.head==r) (r :: l.head) :: l.tail else List(r) :: l
).reverseMap(_.reverse)
Черт, Рекс Керр, за то, что написал ответ, на который я бы пошел. Поскольку существуют незначительные стилистические отличия, здесь я беру:
list.tail.foldLeft(List(list take 1)) { 
    case (acc @ (lst @ hd :: _) :: tl, el) => 
        if (el == hd) (el :: lst) :: tl 
        else (el :: Nil) :: acc 
}
Поскольку элементы идентичны, я не стал беспокоить реверсирование подписок.
list.foldRight(List[List[Int]]()){
  (e, l) => l match {
    case (`e` :: xs) :: fs => (e :: e :: xs) :: fs
    case _ => List(e) :: l
  }
}
или
list.zip(false :: list.sliding(2).collect{case List(a,b) => a == b}.toList)
 .foldLeft(List[List[Int]]())((l,e) => if(e._2) (e._1 :: l.head) :: l.tail 
                                       else List(e._1) :: l ).reverse
[изменить]
//find the hidden way 
//the beauty must be somewhere
//when we talk scala
def split(l: List[Int]): List[List[Int]] = 
  l.headOption.map{x => val (h,t)=l.span{x==}; h::split(t)}.getOrElse(Nil)
У меня есть эти реализации, которые работают вокруг методов коллекций. В конце я проверил в более простых реализациях inits и хвостов и оставил кластер. Каждый новый метод, независимо от того, насколько просто заканчивается сбор большого налога, который трудно увидеть извне. Но здесь реализации я не использовал.
import generic._
import scala.reflect.ClassManifest
import mutable.ListBuffer
import annotation.tailrec
import annotation.unchecked.{ uncheckedVariance => uV }
def inits: List[Repr] = repSequence(x => (x, x.init), Nil)
def tails: List[Repr] = repSequence(x => (x, x.tail), Nil)
def cluster[A1 >: A : Equiv]: List[Repr] =
  repSequence(x => x.span(y => implicitly[Equiv[A1]].equiv(y, x.head)))
private def repSequence(
  f: Traversable[A @uV] => (Traversable[A @uV], Traversable[A @uV]),
  extras: Traversable[A @uV]*): List[Repr] = {
  def mkRepr(xs: Traversable[A @uV]): Repr = newBuilder ++= xs result
  val bb = new ListBuffer[Repr]
  @tailrec def loop(xs: Repr): List[Repr] = {
    val seq = toCollection(xs)
    if (seq.isEmpty)
      return (bb ++= (extras map mkRepr)).result
    val (hd, tl) = f(seq)
    bb += mkRepr(hd)
    loop(mkRepr(tl))
  }
  loop(self.repr)
}
[Edit: Я забыл, что другие люди не будут знать внутренности. Этот код написан изнутри TraversableLike, поэтому он не будет работать из коробки.]
Здесь хвостовое рекурсивное решение, вдохновленное @Kevin Wright и @Landei:
@tailrec
def sliceEqual[A](s: Seq[A], acc: Seq[Seq[A]] = Seq()): Seq[Seq[A]] = {
  s match {
    case fst :: rest =>
      val (l, r) = s.span(fst==)
      sliceEqual(r, acc :+ l)
    case Nil => acc
  }
}
Здесь немного чище:
def groupConsequtive[A](list: List[A]): List[List[A]] = list match {
  case head :: tail =>
    val (t1, t2) = tail.span(_ == head)
    (head :: t1) :: groupConsequtive(t2)
  case _ => Nil  
}
это может быть проще:
val input = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
input groupBy identity values