2010-04-11 11 views
90

W Scali, często używać iterator zrobić for pętli w rosnącym porządku jak:Scala w dół lub maleje dla pętli?

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

Jak to zrobić tak, że idzie od 10 do 1? Domyślam się, że 10 to 1 daje pusty iterator (jak zwykła matematyka zakresu)?

Zrobiłem skrypt Scala, który rozwiązuje go, wywołując odwrotną stronę na iteratorze, ale to nie jest miłe w mojej opinii, czy podążanie tą drogą ma miejsce?

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

Odpowiedz

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: Nie ma za co. Powinienem też wskazać, że istnieje również "do", że można użyć zamiast "to", aby wykluczyć prawy punkt końcowy z zakresu. Lewy punkt końcowy jest zawsze uwzględniany. –

+0

Już wiedziałem o do, aż do jest również funkcją na liczbach całkowitych, jednak "by" musi być funkcją w zakresie/iteratorze, co jest zwracane z funkcji "do" i "do". Dzięki i tak :) – Felix

+3

Odpowiedź Randall jest najlepsza, ale myślę, że 'Range.inclusive (10, 1, -1)' zasługuje na wzmiankę. –

32

Odpowiedź z @Randall jest dobry jak złoto, lecz ze względu na zakończenie chciałem dodać kilka wariantów:

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 dla pierwszego, ale drugi jest zły - mniej czytelny niż "by", a IMO nie powinno być używane pod żadnym pozorem –

+4

Drugi to zło, ale buduje intuicję na tym, co jest dostępne. – Zaheer

6

Po zaprogramowaniu w Pascalu, uważam tę definicję miła w obsłudze:

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 
} 

Używany w ten sposób:

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

Dziękuję za odpowiedź. Mam problem z używaniem tego rozwiązania. Oto mój stacktrace: 'Error: (57, 17) klasa wartości może nie być członkiem innej klasy domniemana klasa RichInt (wartość val: Int) przedłuża AnyVal { ^' – robert

+0

Jako komunikat o błędzie (nie śledzenie stosu) sugeruje, nie możesz zdefiniować klasy wartości wewnątrz innej klasy. Albo zdefiniuj go na zewnątrz, albo w obiekcie, albo usuń część 'extends AnyVal' (która służy tylko do usunięcia trochę narzutów). –

3

Scala oferuje wiele sposobów pracy w pętli w dół.

1-ty Rozwiązanie: z "do" i "o"

//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. Rozwiązanie: Z "z" i "do tyłu"

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

3-ty Rozwiązanie: z "na" tylko

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

Wszystkie te opcje zostały już uwzględnione (lata temu). – jwvh