¿Scala hacia abajo o disminuyendo para bucle?

115

En Scala, a menudo usa un iterador para hacer un for bucle en un orden creciente como:

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

¿Cómo lo harías para que pase de 10 a 1? supongo10 to 1 da un iterador vacío (como las matemáticas de rango habituales).

Hice un script de Scala que lo resuelve llamando a reverse en el iterador, pero en mi opinión no es agradable, ¿es el siguiente el camino a seguir?

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
fuente

Respuestas:

229
scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
Randall Schulz
fuente
2
@Felix: De nada. También debería haber señalado que también untilpuede usar en lugar de topara excluir el punto final de la derecha del rango. Siempre se incluye el punto final de la izquierda.
Randall Schulz
Ya sabía sobre el hasta, el hasta también es una función en los enteros, sin embargo, "por" debe ser una función en el rango / iterador lo que sea que se devuelva de las funciones "hasta" y "hasta". Gracias de todos modos :)
Felix
5
La respuesta de Randall es la mejor, pero creo que Range.inclusive(10, 1, -1)merece una mención.
john sullivan
37

La respuesta de @Randall es tan buena como el oro, pero en aras de la finalización, quería agregar un par de variaciones:

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
fuente
9
+1 para el primero, pero el segundo es malvado: menos legible que byy IMO no debe usarse bajo ninguna circunstancia
om-nom-nom
4
Segundo es el mal sino que construye la intuición de lo que está disponible
Zaheer
10

Scala proporciona muchas formas de trabajar hacia abajo en bucle.

Primera solución: con "to" y "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)
}

Segunda solución: con "to" y "reverse"

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

Tercera solución: 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)
}
Dipak Shaw
fuente
6

Habiendo programado en Pascal, encuentro esta definición agradable de usar:

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
}

Usado de esta manera:

for (i <- 10 downto 0) println(i)
LP_
fuente
Gracias por la respuesta. Tengo problemas para usar esta solución. Aquí está mi stacktrace:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
robert
Como sugiere el mensaje de error (no un seguimiento de pila), no puede definir la clase de valor dentro de otra clase. Definirlo fuera de él, como en un objeto, o eliminar la extends AnyValparte (que solo sirve para eliminar algunos gastos generales).
LP_
1

Puede usar la clase Range:

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

Puedes usar : for (i <- 0 to 10 reverse) println(i)

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

El ciclo se ejecutará hasta el valor == 0, decrementado cada vez en -1.

n1cula
fuente