如何打破循环?
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循环转换为尾递归?
来自Scala Talk at FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261在第22页:
休息并继续Scala没有它们 . 为什么?他们有点必要;更好地使用许多较小的函数问题如何与闭包交互 . 他们不需要!
解释是什么?
17 回答
一种在我们迭代时生成一个范围内的值的方法,直到破坏条件,而不是首先生成整个范围然后迭代它,使用
Iterator
,(灵感来自@RexKerr使用Stream
)这在Scala 2.8中有所改变,它具有使用休息的机制 . 您现在可以执行以下操作:
打破for循环永远不是一个好主意 . 如果您使用for循环,则意味着您知道要迭代的次数 . 使用具有2个条件的while循环 .
例如
要添加Rex Kerr,请回答另一种方法:
由于Scala中还没有
break
,您可以尝试使用return
-statement解决此问题 . 因此,您需要将内部循环放入函数中,否则返回将跳过整个循环 .然而,Scala 2.8包含了一种打破方式
http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html
只需使用while循环:
你有三个(或左右)选项来摆脱循环 .
假设你要总和数字,直到总数大于1000.你试试
除了你想要停止时(总和> 1000) .
该怎么办?有几种选择 .
(1a)使用包含您测试的条件的一些构造 .
(警告 - 这取决于在评估过程中takeWhile测试和foreach如何交错的细节,并且可能不应该在实践中使用!) .
(1b)使用尾递归而不是for循环,利用在Scala中编写新方法的容易程度:
(1c)回到使用while循环
(2)抛出异常 .
(2a)在Scala 2.8中,这已经预先打包在
scala.util.control.Breaks
中,使用的语法看起来很像你熟悉的C / Java旧版:(3)将代码放入方法并使用return .
由于至少有三个我能想到的原因,故意这样做并不容易 . 首先,在大型代码块中,它会比实际上更多或更少,或者需要打破两个循环,你甚至可以注意到,所以如果你能够突破某些东西,那么你就不会发生任何问题 . [908503_ s "loops"不是't actually normal loops--they'方法调用有自己的循环,或者它们是递归,可能实际上也可能不是循环 - 尽管它们是循环的,但是很难想出一种一致的方法来知道"break"等应该做什么 . 所以,为了保持一致,更明智的做法就是不要有"break" .
Note :所有这些都具有功能等价物,您可以返回
sum
的值,而不是将其变异 . 这些是更惯用的Scala . 但是,逻辑仍然是一样的 . (return
变为return x
等) .使用Break模块http://www.tutorialspoint.com/scala/scala_break_statement.htm
这是一个尾递归版本 . 与for-comprehensions相比,它确实有点神秘,但我会说它的功能:)
正如您所看到的,tr函数是外部for-comprehensions的对应部分,而内部函数的tr1则是tr1函数的对应部分 . 如果您知道优化我的版本的方法,欢迎您 .
接近你的解决方案是这样的:
j-iteration在没有新范围的情况下进行,产品生成以及条件都在for语句中完成(不是一个好的表达式 - 我找不到更好的表达式) . 条件是相反的,对于那个问题大小来说相当快 - 也许你可以通过更大的循环来获得一些东西 .
String.reverse隐式转换为RichString,这就是我做2次额外反转的原因 . :)更多数学方法可能更优雅 .
第三方
breakable
包是一种可能的替代方案https://github.com/erikerlandson/breakable
示例代码:
具有讽刺意味的是,
scala.util.control.Breaks
中的Scala中断是一个例外:最好的建议是:不要使用休息,继续和转到! IMO他们是相同的,坏的做法和各种问题的邪恶来源(和热门的讨论),最后“被认为是有害的” . 代码块结构化,在这个示例中,中断也是多余的 . 我们的Edsger W. Dijkstra†写道:
巧妙地使用
find
方法进行收集将为您提供帮助 .我遇到了类似下面代码的情况
我使用的是java lib,其机制是ctx.read在无法找到任何内容时抛出异常 . 我陷入了这样的境地:我必须打破一个循环抛出了异常,但scala.util.control.Breaks.break使用Exception来打破循环,并且它在catch块中因此被捕获 .
我得到了解决这个问题的丑陋方法:第一次进行循环并得到实际长度的计数 . 并将其用于第二个循环 .
当您使用一些java库时,从Scala中取出并不是那么好 .
我是Scala的新手,但是如何避免抛出异常并重复方法:
像这样用它:
如果你不想打破:
使用Breaks类打破循环的基本方法 . 通过声明循环可破坏 .
我们可以在scala中做到
output :