2017-07-17 1 views
-1

Avoir une séquence d'entier positif, besoin de diviser la séquence de la droite à l'élément lorsque la somme jusqu'à cet élément est inférieure ou égale à un seuil. Par exemple,Scala Split Séq d'Int de droite lorsque les résultats cumulés satisfont la condition

val seq = Seq(9,8,7,6,5,4,3,2,1) 

Le seuil est de 10, de sorte que le résultat est

Seq(9,8,7,6,5) and Seq(4,3,2,1) 

J'ai essayé dropWhile et scanLeft après inverse, cependant, ils sont soit du second degré ou linéaire, mais compliquée. Puisque notre séquence peut être très longue, mais normalement le seuil est petit et très peu d'éléments du côté droit répondront à la condition. Je me demande s'il existe une meilleure façon de le faire.

+0

mieux que quoi? vous devez toujours présenter votre approche à l'avance – greenshade

Répondre

0

Ceci s'arrêtera dès que le seuil est atteint. Malheureusement, il utilise un retour à la rupture.

val seq = Seq(9,8,7,6,5,4,3,2,1) 
val threshold = 10 

def processList(): (Seq[Int], Int) = { 
    seq.foldRight((Seq[Int](), 0)) { 
    case (elem, (acc, total)) => 
     if (total + elem <= threshold) { 
     (elem +: acc, total + elem) 
     } else { 
     return (acc, total) 
     } 
    } 
} 

processList() 
0

On dirait qu'il n'y a pas une bonne façon de le faire avec des méthodes intégrées, mais vous pouvez l'implémenter:

def splitRightCumulative[A, B](xs: Seq[A])(start: B)(f: (B, A) => B, cond: B => Boolean): (Seq[A], Seq[A]) = { 
    def _loop(current: B, xs: Seq[A], acc: Seq[A]): (Seq[A], Seq[A]) = { 
     val next = f(current, xs.head) 
     if (cond(next)) { 
     _loop(next, xs.tail, xs.head +: acc) 
     } else { 
     (xs.reverse, acc) 
     } 
    } 
    _loop(start, xs.reverse, Seq.empty) 
    } 

    val xs = List(9, 8, 7, 6, 5, 4, 3, 2, 1) 
    val (left, right) = splitRightCumulative(xs)(0)(_ + _, _ <= 10) 

Le second paramètre de type (B) pourrait ne pas être nécessaire si vous 'accumule toujours le même type que ce qui est dans votre collection.