recorrer listas lista funciones scala collections

funciones - listas en scala



Función de lista Scala para agrupar elementos idénticos consecutivos (7)

Dado por ejemplo:

List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)

Me gustaría llegar a:

List(List(5), List(2), List(3, 3, 3), List(5, 5), List(3, 3), List(2, 2, 2))

Asumiría que hay una función de lista simple que hace esto, pero no puedo encontrarlo.


Este es el truco que normalmente uso:

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) }

En realidad ... No lo es, suelo abstraer el tipo de colección y optimizar con recursividad de cola también, pero quería mantener la respuesta simple.


Maldición Rex Kerr, por escribir la respuesta que iría. Como hay pequeñas diferencias de estilo, esta es mi opinión:

list.tail.foldLeft(List(list take 1)) { case (acc @ (lst @ hd :: _) :: tl, el) => if (el == hd) (el :: lst) :: tl else (el :: Nil) :: acc }

Como los elementos son idénticos, no me molesté en invertir las sublistas.


val xs = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)

Aquí hay otra manera.

(List(xs.take(1)) /: xs.tail)((l,r) => if (l.head.head==r) (r :: l.head) :: l.tail else List(r) :: l ).reverseMap(_.reverse)


Tengo estas implementaciones de trabajar en métodos de cobranza. Al final, verifiqué implementaciones más simples de inits y colas y dejé fuera el clúster. Cada nuevo método, sin importar cuán simple sea, termina recabando un gran impuesto que es difícil de ver desde el exterior. Pero aquí está la implementación que no usé.

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) }

[Editar: Se me olvida que otras personas no sabrán las partes internas. Este código está escrito desde dentro de TraversableLike, por lo que no se ejecutará fuera de la caja.]


list.foldRight(List[List[Int]]()){ (e, l) => l match { case (`e` :: xs) :: fs => (e :: e :: xs) :: fs case _ => List(e) :: l } }

O

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

[Editar]

//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)


esto podría ser más simple:

val input = List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2) input groupBy identity values


Aquí hay una solución recursiva de la cola inspirada por @Kevin Wright y @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 } }