Scala向下或递减的循环?

129

在Scala中,你通常使用迭代器来进行递增的for循环,例如:

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

如何让它从10到1?我猜10 to 1会得到一个空的迭代器(就像通常的数学范围一样)?

我编写了一个Scala脚本,通过在迭代器上调用reverse来解决它,但我认为这不太好,以下是正确的方式吗?

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))
7个回答

253
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”,从而排除范围的右端点。左端点始终包含在内。 - Randall Schulz
我已经知道了"until","until"也是整数的一个函数,但是"by"必须是从"to"和"until"函数返回的范围/迭代器的一个函数。无论如何,谢谢 :) - Felix
6
Randall的回答是最好的,但我认为Range.inclusive(10, 1, -1)值得一提。 - john sullivan

44

@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.

10
第一个没问题,但第二个很糟糕——比“by”难以阅读,在任何情况下都不应使用(依我之见)。 - om-nom-nom
5
第二个选项是邪恶的,但可以通过现有的情况来建立直觉。 - Zaheer
谢谢,reverse 对于独占开始和包含结束很好用,例如 1 until x reverse 而不是 x-1 to 1 by -1 - Eric Jiang

16

Scala提供了许多方法来在循环中向下工作。

第一种解决方案:使用 "to" 和 "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)
}

第二个解决方案:使用 "to" 和 "reverse"

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

第三种解决方案:只使用“to”

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

感谢您的回答。我在使用这个解决方案时遇到了问题。以下是我的堆栈跟踪:错误:(57,17)值类不能是另一个类的成员 implicit class RichInt(val value: Int) extends AnyVal { ^ - robert
正如错误信息(而不是堆栈跟踪)所示,您不能在另一个类内部定义值类。要么将其定义在外部,例如在对象中,要么删除 extends AnyVal 部分(这只是为了消除一些开销)。 - Lionel Parreaux

2
您可以使用以下代码: for (i <- 0 到 10 反向) 打印(i)

"Original Answer"翻译成中文为"最初的回答"。

2
您可以使用Range类:
val r1 = new Range(10, 0, -1)
for {
  i <- r1
} println(i)

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

循环将一直执行,直到值等于0,每次递减1。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接