127 votes

Scala boucle for descendante ou décroissante ?

En Scala, on utilise souvent un itérateur pour faire une for boucle dans un ordre croissant comme :

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

Comment faire pour que ça passe de 10 à 1 ? Je suppose 10 to 1 donne un itérateur vide (comme les mathématiques habituelles de la gamme) ?

J'ai fait un Scala script qui le résout en appelant reverse sur l'itérateur, mais ce n'est pas très joli à mon avis, est-ce que ce qui suit 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))

249voto

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

2 votes

@Felix : De rien. J'aurais dû également signaler qu'il existe aussi until que vous pouvez utiliser à la place de to pour exclure l'extrémité droite de la plage. Le point d'extrémité gauche est toujours inclus.

0 votes

Je connaissais déjà le until, le until est aussi une fonction sur les Integers, cependant, le "by" doit être une fonction sur l'intervalle/iterator quel que soit le retour des fonctions "to" et "until". Merci quand même :)

5 votes

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

43voto

Chirlo Points 1861

La réponse de @Randall est bonne comme l'or, mais pour compléter, 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.

10 votes

+1 pour le premier, mais le deuxième est mauvais -- moins lisible que by et IMO ne devrait pas être utilisé dans n'importe quelles circonstances.

5 votes

Le second est mauvais mais construit une intuition sur ce qui est disponible.

0 votes

Merci, reverse est utile pour un début exclusif et une fin inclusive, par exemple. 1 until x reverse au lieu de x - 1 to 1 by -1 .

15voto

Dipak Shaw Points 341

Scala fournit de nombreuses façons de travailler sur la partie descendante d'une boucle.

1ère solution : avec "à" 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 "to" et "reverse"

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

6voto

LP_ Points 121

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)

0 votes

Merci pour la réponse. J'ai des difficultés à 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 { ^

0 votes

Comme le suggère le message d'erreur (pas de trace de pile), vous ne pouvez pas définir la classe de valeur à l'intérieur d'une autre classe. Soit vous la définissez à l'extérieur de celle-ci, par exemple dans un objet, soit vous supprimez l'élément extends AnyVal (qui ne sert qu'à supprimer une partie de la charge).

2voto

KaaPex Points 471

Vous pouvez utiliser la classe Range :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X