2010-04-11 16 views
90

In Scala, si utilizza spesso un iteratore per fare un loop for in un ordine crescente come:Scala verso il basso o decrescente per loop?

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

Come si dovrebbe fare in modo che va da 10 a 1? Immagino che 10 to 1 dia un iteratore vuoto (come la solita matematica della gamma)?

Ho creato uno script di Scala che lo risolve richiamando l'inverso sull'iteratore, ma non è bello secondo me, la seguente è la strada da seguire?

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

risposta

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

@Felix: prego. Avrei anche dovuto notare che c'è anche 'until' che puoi usare al posto di' to' per escludere il punto finale della mano destra dall'intervallo. L'endpoint di sinistra è sempre incluso. –

+0

Sapevo già fino a quando, fino a quando è anche una funzione su Interi, tuttavia, "per" deve essere una funzione sull'intervallo/iteratore, qualsiasi cosa sia restituito dalle funzioni "a" e "fino a". Grazie comunque :) – Felix

+3

La risposta di Randall è la migliore, ma penso che "Range.inclusive (10, 1, -1)" meriti di essere menzionato. –

32

La risposta da @Randall è buono come l'oro, ma per amore di completamento ho voluto aggiungere un paio di variazioni:

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 è il male - meno leggibile di 'by' e IMO non deve essere utilizzato in nessuna circostanza –

+4

Il secondo è il male ma costruisce l'intuizione su ciò che è disponibile – Zaheer

6

aver programmato in Pascal, trovo questa definizione 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) 
+0

Grazie per la risposta. Ho problemi con l'utilizzo di questa soluzione. Ecco la mia stacktrace: 'Errore: (57, 17) classe di valore non può essere un membro di un'altra classe implicita RichInt classe (valore val: Int) si estende AnyVal { ^' – robert

+0

Come il messaggio di errore (non una traccia dello stack) suggerisce, non è possibile definire la classe di valore all'interno di un'altra classe. Definirlo al di fuori di esso, oke in un oggetto, o rimuovere la parte 'extends AnyVal' (che serve solo a rimuovere alcuni overhead). –

3

Scala offre molti modi per lavorare in loop in discesa.

1 ° Soluzione: con la "a" e "da"

//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 ° Soluzione: Con "a" e "reverse"

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

3 ° Soluzione: con la "a" solo

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

Tutte queste opzioni sono già state trattate (anni fa). – jwvh

Problemi correlati