Scala vers le bas ou décroissant pour la boucle?


115

Dans Scala, vous utilisez souvent un itérateur pour faire une forboucle dans un ordre croissant comme:

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

Comment feriez-vous pour que ça passe de 10 à 1? Je suppose que 10 to 1donne un itérateur vide (comme les mathématiques de plage habituelles)?

J'ai fait un script Scala qui le résout en appelant reverse sur l'itérateur, mais ce n'est pas sympa à mon avis, est-ce que la suite est la voie à suivre?

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

Réponses:


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: De rien. J'aurais également dû souligner qu'il y a aussi untilque vous pouvez utiliser à la place de topour exclure le point final de droite de la plage. Le point de terminaison de gauche est toujours inclus.
Randall Schulz

Je connaissais déjà le till, le till est aussi une fonction sur les entiers, cependant, "by" doit être une fonction sur la plage / l'itérateur tout ce qui est retourné par les fonctions "to" et "until". Merci quand même :)
Felix

5
La réponse de Randall est la meilleure, mais je pense qu'elle Range.inclusive(10, 1, -1)mérite d'être mentionnée.
john sullivan

37

La réponse de @Randall est aussi bonne que l'or, mais par souci de finition, je voulais ajouter quelques variantes:

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 pour le premier, mais le second est mauvais - moins lisible que byet l'OMI ne doit en aucun cas être utilisé
om-nom-nom

4
Le deuxième est mal mais construit l'intuition sur ce qui est disponible
Zaheer

10

Scala fournit de nombreuses façons de travailler en boucle vers le bas.

1ère solution: avec "vers" et "par"

//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ème solution: avec "vers" et "inverser"

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

3ème solution: avec "à" uniquement

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

6

Ayant programmé en Pascal, je trouve cette définition agréable à utiliser:

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
}

Utilisé de cette façon:

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

Merci pour la réponse. J'ai du mal à utiliser cette solution. Voici mon stacktrace:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
robert

Comme le suggère le message d'erreur (pas une trace de pile), vous ne pouvez pas définir la classe de valeur à l'intérieur d'une autre classe. Soit le définir en dehors de celui-ci, soit comme dans un objet, soit supprimer la extends AnyValpièce (ce qui ne sert qu'à supprimer une surcharge).
LP_

1

Vous pouvez utiliser la classe Range:

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

1

Vous pouvez utiliser : for (i <- 0 to 10 reverse) println(i)


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

La boucle s'exécutera jusqu'à la valeur == 0, décrémentée à chaque fois de -1.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.