我如何打破一个循环?

var largest=0
for(i<-999 to 1 by -1) {
    for (j<-i to 1 by -1) {
        val product=i*j
        if (largest>product)
            // I want to break out here
        else
           if(product.toString.equals(product.toString.reverse))
              largest=largest max product
    }
}

如何将嵌套for循环转换为尾递归?

来自FOSDEM 2009 Scala Talk http://www.slideshare.net/Odersky/fosdem-2009-1013261 第22页:

中断并继续 Scala没有它们。为什么? 它们有点迫不得已;最好使用许多较小的函数 发布如何与闭包交互。 他们是不需要的!

怎么解释呢?


当前回答

import scala.util.control._

object demo_brk_963 
{
   def main(args: Array[String]) 
   {
      var a = 0;
      var b = 0;
      val numList1 = List(1,2,3,4,5,6,7,8,9,10);
      val numList2 = List(11,12,13);

      val outer = new Breaks; //object for break
      val inner = new Breaks; //object for break

      outer.breakable // Outer Block
      {
         for( a <- numList1)
         {
            println( "Value of a: " + a);

            inner.breakable // Inner Block
            {
               for( b <- numList2)
               {
                  println( "Value of b: " + b);

                  if( b == 12 )
                  {
                      println( "break-INNER;");
                       inner.break;
                  }
               }
            } // inner breakable
            if( a == 6 )
            {
                println( "break-OUTER;");
                outer.break;
            }
         }
      } // outer breakable.
   }
}

打破循环的基本方法,使用Breaks类。 通过将循环声明为可打破的。

其他回答

只需使用while循环:

var (i, sum) = (0, 0)
while (sum < 1000) {
  sum += i
  i += 1
}

接近你的解决方案是这样的:

var largest = 0
for (i <- 999 to 1 by -1;
  j <- i to 1 by -1;
  product = i * j;
  if (largest <= product && product.toString.reverse.equals (product.toString.reverse.reverse)))
    largest = product

println (largest)

j迭代是在没有新的作用域的情况下进行的,产品生成和条件都是在for语句中完成的(这不是一个好的表达式-我没有找到更好的表达式)。对于这个问题大小来说,条件是反向的,这是相当快的——也许对于更大的循环,您可以通过中断获得一些东西。

字符串。reverse隐式转换为RichString,这就是为什么我做了2个额外的反转。:)一个更数学的方法可能会更优雅。

由于Scala中还没有break,您可以尝试使用return语句来解决这个问题。因此,您需要将内部循环放入函数中,否则返回将跳过整个循环。

然而,Scala 2.8包含了一种打破的方法

http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html

我遇到了类似下面代码的情况

 for(id<-0 to 99) {
    try {
      var symbol = ctx.read("$.stocks[" + id + "].symbol").toString
      var name = ctx.read("$.stocks[" + id + "].name").toString
      stocklist(symbol) = name
    }catch {
      case ex: com.jayway.jsonpath.PathNotFoundException=>{break}
    }
  }

我正在使用一个java库和机制是ctx。read在找不到任何东西时抛出异常。 我被困在这样的情况中:当抛出异常时,我必须打破循环,但是scala.util.control. break .break使用异常来打破循环,并且它在catch块中,因此它被捕获。

我有一个丑陋的方法来解决这个问题:第一次执行循环,并获得实际长度的计数。 然后用它来做第二个循环。

当你使用一些java库时,从Scala中解脱出来并不是那么好。

这是一个尾部递归的版本。不可否认,与for推导式相比,它有点晦涩,但我认为它是功能性的:)

def run(start:Int) = {
  @tailrec
  def tr(i:Int, largest:Int):Int = tr1(i, i, largest) match {
    case x if i > 1 => tr(i-1, x)
    case _ => largest
  }

  @tailrec
  def tr1(i:Int,j:Int, largest:Int):Int = i*j match {
    case x if x < largest || j < 2 => largest
    case x if x.toString.equals(x.toString.reverse) => tr1(i, j-1, x)
    case _ => tr1(i, j-1, largest)
  }

  tr(start, 0)
}

如您所见,tr函数是外部for推导式的对应函数,tr1是内部for推导式的对应函数。如果你知道如何优化我的版本,欢迎你。