7
votes

Comment regrouper une séquence répétée de longueur variable dans Scala

J'ai une collection d'INT qui se répètent dans un motif:

class IteratorW[A](itr: Iterator[A]) {
  def groupWhen(fn: A => Boolean): Iterator[Seq[A]] = {
    val bitr = itr.buffered
    new Iterator[Seq[A]] {
      override def hasNext = bitr.hasNext
      override def next = {
        val xs = collection.mutable.ListBuffer(bitr.next)
        while (bitr.hasNext && !fn(bitr.head)) xs += bitr.next
        xs.toSeq
      }
    }
  }
}
implicit def ToIteratorW[A](itr: Iterator[A]): IteratorW[A] = new IteratorW(itr)

> repeatingSequence.iterator.groupWhen(_ == 1).toSeq
List(List(1,2,3), List(1,2,3,4), List(1,2), List(1,2,3,4,5))


3 commentaires

Quelle version de scala utilisez-vous?


Quel devrait être le résultat de la liste (2) .iterator.groupwhen (_ == 1)?


Thomas Jung - Je penserais que cela devrait renvoyer une liste vide. Il n'y a pas de groupe en commençant par 1 dans cet exemple, il devrait donc jeter cela.


4 Réponses :


2
votes

Aussi bien tout savoir, le pli peut tout faire ...;)

  val rs = List(1,2,3,1,2,3,4,1,2,1,2,3,4,5)
  val res = (rs++List(1)).foldLeft((List[List[Int]](),List[Int]()))((acc,e) => acc match {
    case (res,subl) => {
      if (e == 1) ((subl.reverse)::res,1::Nil) else (res, e::subl)
    }
  })
  println(res._1.reverse.tail)


0 commentaires

9
votes

Compte tenu d'un itérateur ITR , cela fera le truc: xxx


3 commentaires

Belle façon de faire face à la perte de la valeur de la tête ( Problèmes.scala-lang.org/Browse / Si-3581 ). Et si vous laissez tomber la dernière toliste, cela fonctionne sur un itérateur infini.


Et si iter.hasnext == false ?


Huynhjl - En effet, vous auriez besoin d'un chèque explicite pour cela, je ne voulais pas distraire de la logique de base, cependant :)



2
votes

Voici une solution non exactement élégante que j'ai battue avec span : xxx


0 commentaires

1
votes
import scala.collection.mutable.ListBuffer
import scala.collection.breakOut

val repeatingSequence = List(1,2,3,1,2,3,4,1,2,1,2,3,4,5)
val groupedBySequence: List[List[Int]] = repeatingSequence.foldLeft(ListBuffer[ListBuffer[Int]]()) {
  case (acc, 1) => acc += ListBuffer(1)
  case (acc, n) => acc.last += n; acc
}.map(_.toList)(breakOut)

0 commentaires