2017-07-18 1 views
1

Wie folgenden nicht funktionsfähig zu machen, aber einfacher Code funktioneller:Beenden Schleife vor Ende

def foo2(iSeq: Seq[Int]): Seq[(Int, Boolean)] = { 
    var seq = Seq[(Int, Boolean)]() 
    iSeq.foreach{ i=> 
     println("i = " + i) 
     val res = (i,i>=0) 
     seq = seq ++ Seq(res) 
     if (res._2==false) return seq 
    } 
    seq 
} 

Idee im Code Schleife Seq bis zum ersten Test nicht besteht, nicht weiter, weil in dem realen Code der Test ist teuer zu tun. Zurückgegebene Seq sollte alle Elemente vor und einschließlich der fehlgeschlagenen enthalten.

Ausgabe des Codes ist wie folgt:

scala> foo2(Seq(1,2,-3,4)) 
i = 1 
i = 2 
i = -3 
res3: Seq[(Int, Boolean)] = List((1,true), (2,true), (-3,false)) 

scala> foo2(Seq(1,2,3,4)) 
i = 1 
i = 2 
i = 3 
i = 4 
res4: Seq[(Int, Boolean)] = List((1,true), (2,true), (3,true), (4,true)) 

ich folgenden ersten Versuch gemacht:

def fooo(iTail: Seq[Int], resSeq: Seq[(Int,Boolean)]): Seq[(Int,Boolean)] = { 
    if (iTail.isEmpty) return resSeq 
    if (!resSeq.isEmpty && resSeq.last._1<0) return resSeq 
    println("i = " + iTail.head) 
    val res = (iTail.head,iTail.head>=0) 
    val seq = resSeq ++ Seq(res) 
    fooo(iTail.tail, seq) 
    } 

Ausgang ist:

scala> fooo(Seq(1,2,3,4,5),Seq()) 
i = 1 
i = 2 
i = 3 
i = 4 
i = 5 
res0: Seq[(Int, Boolean)] = List((1,true), (2,true), (3,true), (4,true), (5,true)) 

scala> fooo(Seq(1,2,-3,4,5),Seq()) 
i = 1 
i = 2 
i = -3 
res1: Seq[(Int, Boolean)] = List((1,true), (2,true), (-3,false)) 

So funktioniert es aber gibt es eine prägnanter oder "scalaish" Weise, dies zu kodieren?

Über die Leistung: Code verwendet resSeq.last. Ist es schneller, zusätzliche Parameter "lastValue" in der rekursiven Funktion fooo zu verwenden, als resSeq.last zu verwenden?

+0

Idk über idiomatische, aber diese frühe Rückkehr sollte wahrscheinlich nicht auf einer Zeile wie diese vollgestopft werden. Ich würde dies auf einen vollständigen if/else-Baum mit geschweiften Klammern erweitern, um klarer zu machen, dass es beendet werden kann, ohne die untere Hälfte der Funktion auszuführen. – Carcigenicate

Antwort

1

Wird das tun?

Seq(1,2,3).takeWhile(_ < 3) 

P.S. Danke, @mrmcgreg, ich habe nicht sehr gut gelesen. Um die erste fehlgeschlagen zu lassen:

val s = Seq(1,2,3).span(_ < 3) 
s._1 ++ s._2.take(1) 

P.S. Und um die Vergleichswerte einzuschließen:

val s = Seq(1,2,3).map(e => (e, compare(e)).span(test(_._2)) 
s._1 ++ s._2.take(1) 
+0

Sieht nicht ganz richtig aus, weil OP den ersten Test einschließen möchte, der den Test nicht besteht. – mrmcgreg

+0

Ich muss den Vergleichs-Rückgabewert einschließen. In diesem Beispiel ist es boolesch, aber in echtem Code kann es mehr Werte als wahr/falsch haben und die zurückgegebene Sequenz muss den fehlgeschlagenen Vergleich enthalten. – user4955663

+0

Sie können Ihre Sequenz transformieren: 'Seq (1,2,3) .map (e => (e, f (e)). Span (_._ 2 <3)' ... –