Scala вниз или уменьшение цикла?


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

Я уже знал, что до, до также является функцией для целых чисел, однако «by» должно быть функцией диапазона / итератора, независимо от того, что возвращается из функций «до» и «до». В любом случае спасибо :)
Феликс

5
Ответ Рэндалла лучший, но я думаю, что он Range.inclusive(10, 1, -1)заслуживает упоминания.
Джон Салливан

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_ 05

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.