Scala verso il basso o decrescente per ciclo?


115

In Scala, usi spesso un iteratore per eseguire un forciclo in ordine crescente come:

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

Come lo faresti in modo che passi da 10 a 1? Immagino che 10 to 1dia un iteratore vuoto (come la solita matematica della gamma)?

Ho creato uno script in Scala che lo risolve chiamando reverse sull'iteratore, ma non è carino secondo me, è la strada da percorrere?

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

Risposte:


229
scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

2
@Felix: sei il benvenuto. Avrei anche dovuto sottolineare che c'è anche untilche puoi usare al posto di toper escludere il punto finale destro dall'intervallo. L'endpoint di sinistra è sempre incluso.
Randall Schulz

Conoscevo già il until, il until è anche una funzione su Integers, tuttavia, "by" deve essere una funzione sull'intervallo / iteratore qualunque cosa venga restituita dalle funzioni "to" e "until". Grazie comunque :)
Felix

5
La risposta di Randall è la migliore, ma penso che Range.inclusive(10, 1, -1)meriti una menzione.
john sullivan

37

La risposta di @Randall è buona come l'oro, ma per amor di completamento volevo aggiungere un paio di varianti:

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.

9
+1 per il primo, ma il secondo è malvagio - meno leggibile di bye IMO non dovrebbe essere usato in nessuna circostanza
om-nom-nom

4
Il secondo è cattivo ma costruisce l'intuizione su ciò che è disponibile
Zaheer

10

Scala offre molti modi per lavorare in loop verso il basso.

1a soluzione: con "a" e "di"

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

Seconda soluzione: con "a" e "inverso"

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

Terza soluzione: solo con "a"

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

6

Avendo programmato in Pascal, trovo che questa definizione sia piacevole da usare:

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
}

Usato in questo modo:

for (i <- 10 downto 0) println(i)

Grazie per la risposta. Ho problemi a utilizzare questa soluzione. Ecco il mio stacktrace:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
robert

Come suggerisce il messaggio di errore (non un'analisi dello stack), non è possibile definire la classe di valore all'interno di un'altra classe. O definiscilo al di fuori di esso, oike in un oggetto, o rimuovi la extends AnyValparte (che serve solo a rimuovere un po 'di overhead).
LP_

1

Puoi usare la classe Range:

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

1

Puoi usare : for (i <- 0 to 10 reverse) println(i)


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

Il ciclo verrà eseguito fino al valore == 0, decrementato ogni volta di -1.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.