Масштабування вниз або зменшення для циклу?


115

У Scala ви часто використовуєте ітератор, щоб робити forцикл у зростаючому порядку, наприклад:

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

Як би ви це зробили, щоб вона пройшла від 10 до 1? Я думаю, 10 to 1дає порожній ітератор (як звичайна математика діапазону)?

Я створив сценарій Scala, який вирішує його, викликаючи зворотній зв'язок на ітераторі, але це не приємно, на мою думку, чи слід наступним шляхом?

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

Відповіді:


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: Ласкаво просимо. Я також повинен зазначити, що існує також untilте, що ви можете використовувати замість того, toщоб виключити праву кінцеву точку з діапазону. Ліва кінцева точка завжди включена.
Рандалл Шульц

Я вже знав про до, до, поки функція також є цілим числом, однак, "від" повинна бути функцією в діапазоні / ітераторі, що б не повернулося з функцій "до" і "до". Все одно дякую :)
Фелікс

5
Відповідь Рендала найкраща, але я думаю, Range.inclusive(10, 1, -1)заслуговує на згадку.
John sullivan

37

Відповідь від @Randall хороша як золото, але заради завершення я хотів додати пару варіацій:

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 для першого, але для другого є злом - менш читабельним, ніж byІМО не слід застосовувати ні за яких обставин
om-nom-nom

4
Друге - зло, але будує інтуїцію на тому, що є в наявності
Захер,

10

Scala пропонує безліч способів працювати вниз в циклі.

1-е рішення: з "до" і "по"

//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-е рішення: З "до" та "назад"

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

3-е рішення: лише з "до"

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

6

Програмувавши в Паскалі, я вважаю це визначення приємним у використанні:

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
}

Використовується таким чином:

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

Дякую за відповідь. У мене виникають проблеми з використанням цього рішення. Ось мій стек-трек:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
Роберт

Як підказує повідомлення про помилку (не слід стека), ви не можете визначити клас значення всередині іншого класу. Або визначте його поза нею, ввімкніть об'єкт або видаліть extends AnyValдеталь (яка служить лише для видалення накладних витрат).
LP_

1

Ви можете використовувати клас Range:

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


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

Цикл виконується до значення == 0, щоразу зменшується на -1.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.