Scala nach unten oder abnehmend für Schleife?

114

In Scala verwenden Sie häufig einen Iterator, um eine forSchleife in aufsteigender Reihenfolge auszuführen, z.

for(i <- 1 to 10){ code }

Wie würden Sie es tun, damit es von 10 auf 1 geht? Ich denke, 10 to 1gibt einen leeren Iterator (wie übliche Bereichsmathematik)?

Ich habe ein Scala-Skript erstellt, das es löst, indem ich den Iterator umgekehrt aufrufe, aber meiner Meinung nach ist es nicht schön. Ist das Folgende der richtige Weg?

def nBeers(n:Int) = n match {

    case 0 => ("No more bottles of beer on the wall, no more bottles of beer." +
               "\nGo to the store and buy some more, " +
               "99 bottles of beer on the wall.\n")

    case _ => (n + " bottles of beer on the wall, " + n +
               " bottles of beer.\n" +
               "Take one down and pass it around, " +
              (if((n-1)==0)
                   "no more"
               else
                   (n-1)) +
                   " bottles of beer on the wall.\n")
}

for(b <- (0 to 99).reverse)
    println(nBeers(b))
Felix
quelle

Antworten:

228
scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
Randall Schulz
quelle
1
@ Felix: Gern geschehen. Ich hätte auch darauf hinweisen sollen, untildass Sie anstelle von auch toden rechten Endpunkt aus dem Bereich ausschließen können. Der linke Endpunkt ist immer enthalten.
Randall Schulz
Ich wusste bereits über das Bis, das Bis ist auch eine Funktion für Ganzzahlen, jedoch muss "by" eine Funktion für den Bereich / Iterator sein, was auch immer von den Funktionen "to" und "till" zurückgegeben wird. Trotzdem danke :)
Felix
5
Randalls Antwort ist die beste, aber ich denke, sie Range.inclusive(10, 1, -1)verdient Erwähnung.
John Sullivan
37

Die Antwort von @Randall ist gut wie Gold, aber der Vollständigkeit halber wollte ich ein paar Variationen hinzufügen:

scala> for (i <- (1 to 10).reverse) {code} //Will count in reverse.

scala> for (i <- 10 to(1,-1)) {code} //Same as with "by", just uglier.
Chirlo
quelle
9
+1 für den ersten, aber der zweite ist böse - weniger lesbar als byund IMO sollte unter keinen Umständen verwendet werden
om-nom-nom
4
Der zweite ist böse, baut aber die Intuition auf dem auf, was verfügbar ist
Zaheer
10

Scala bietet viele Möglichkeiten, um in einer Schleife nach unten zu arbeiten.

1. Lösung: mit "to" und "by"

//It will print 10 to 0. Here by -1 means it will decremented by -1.     
for(i <- 10 to 0 by -1){
    println(i)
}

2. Lösung: Mit "to" und "reverse"

for(i <- (0 to 10).reverse){
    println(i)
}

3. Lösung: nur mit "bis"

//Here (0,-1) means the loop will execute till value 0 and decremented by -1.
for(i <- 10 to (0,-1)){
    println(i)
}
Dipak Shaw
quelle
6

Nachdem ich in Pascal programmiert habe, finde ich diese Definition gut zu verwenden:

implicit class RichInt(val value: Int) extends AnyVal {
  def downto (n: Int) = value to n by -1
  def downtil (n: Int) = value until n by -1
}

So verwendet:

for (i <- 10 downto 0) println(i)
LP_
quelle
Vielen Dank für die Antwort. Ich habe Probleme mit dieser Lösung. Hier ist meine Stapelspur:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
Robert
Wie aus der Fehlermeldung (keine Stapelverfolgung) hervorgeht, können Sie die Wertklasse nicht innerhalb einer anderen Klasse definieren. Definieren Sie es entweder außerhalb davon, wie in einem Objekt, oder entfernen Sie das extends AnyValTeil (das nur dazu dient, etwas Overhead zu entfernen).
LP_
1

Sie können die Range-Klasse verwenden:

val r1 = new Range(10, 0, -1)
for {
  i <- r1
} println(i)
KaaPex
quelle
1

Sie können verwenden: for (i <- 0 to 10 reverse) println(i)

Jonny
quelle
0
for (i <- 10 to (0,-1))

Die Schleife wird bis zum Wert == 0 ausgeführt, der jedes Mal um -1 dekrementiert wird.

n1cula
quelle