Как мне выйти из цикла в Scala? - PullRequest
259 голосов
/ 30 апреля 2010

Как мне разорвать петлю?

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

Как превратить вложенные циклы в хвостовую рекурсию?

Из Scala Talk на FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261 на 22 странице:

Перерыв и продолжить У Скалы их нет. Зачем? Они немного необходимы; лучше использовать много мелких функций Вопрос, как взаимодействовать с замыканиями. Они не нужны!

Какое объяснение?

Ответы [ 18 ]

2 голосов
/ 05 марта 2017

Сторонний пакет breakable является одной из возможных альтернатив

https://github.com/erikerlandson/breakable

Пример кода:

scala> import com.manyangled.breakable._
import com.manyangled.breakable._

scala> val bkb2 = for {
     |   (x, xLab) <- Stream.from(0).breakable   // create breakable sequence with a method
     |   (y, yLab) <- breakable(Stream.from(0))  // create with a function
     |   if (x % 2 == 1) continue(xLab)          // continue to next in outer "x" loop
     |   if (y % 2 == 0) continue(yLab)          // continue to next in inner "y" loop
     |   if (x > 10) break(xLab)                 // break the outer "x" loop
     |   if (y > x) break(yLab)                  // break the inner "y" loop
     | } yield (x, y)
bkb2: com.manyangled.breakable.Breakable[(Int, Int)] = com.manyangled.breakable.Breakable@34dc53d2

scala> bkb2.toVector
res0: Vector[(Int, Int)] = Vector((2,1), (4,1), (4,3), (6,1), (6,3), (6,5), (8,1), (8,3), (8,5), (8,7), (10,1), (10,3), (10,5), (10,7), (10,9))
2 голосов
/ 18 мая 2010

Близко к вашему решению будет это:

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 (не очень хорошее выражение - я не нашел лучшего). Условие меняется на противоположное, что довольно быстро для такого размера задачи - может быть, вы получите что-то с разрывом для больших циклов.

String.reverse неявно преобразуется в RichString, поэтому я делаю 2 дополнительных реверса. :) Более математический подход может быть более элегантным.

1 голос
/ 16 декабря 2018

Ниже приведен код для простого разрыва цикла

import scala.util.control.Breaks.break

object RecurringCharacter {
  def main(args: Array[String]) {
    val str = "nileshshinde";

    for (i <- 0 to str.length() - 1) {
      for (j <- i + 1 to str.length() - 1) {

        if (str(i) == str(j)) {
          println("First Repeted Character " + str(i))
          break()     //break method will exit the loop with an Exception "Exception in thread "main" scala.util.control.BreakControl"

        }
      }
    }
  }
}
1 голос
/ 26 февраля 2016

Умный Использование метода find для сбора подойдет вам.

var largest = 0
lazy val ij =
  for (i <- 999 to 1 by -1; j <- i to 1 by -1) yield (i, j)

val largest_ij = ij.find { case(i,j) =>
  val product = i * j
  if (product.toString == product.toString.reverse)
    largest = largest max product
  largest > product
}

println(largest_ij.get)
println(largest)
1 голос
/ 23 июня 2014

Как ни странно, разрыв Scala в scala.util.control.Breaks является исключением:

def break(): Nothing = { throw breakException }

Лучший совет: НЕ используйте перерыв, продолжайте и переходите! ИМО - это то же самое, плохая практика и злой источник всех видов проблем (и горячие дискуссии) и, наконец, «считается вредным» Блок кода структурирован, также в этом примере разрывы излишни. Наш Эдсгер В. Дейкстра † написал:

Качество программистов - это уменьшающаяся функция плотности операторов go в программах, которые они производят.

0 голосов
/ 10 мая 2018
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. Объявляя петлю как разрушаемую.

0 голосов
/ 21 января 2016

Я новичок в Scala, но как насчет этого, чтобы не создавать исключений и повторять методы:

object awhile {
def apply(condition: () => Boolean, action: () => breakwhen): Unit = {
    while (condition()) {
        action() match {
            case breakwhen(true)    => return ;
            case _                  => { };
        }
    }
}
case class breakwhen(break:Boolean);

используйте это так:

var i = 0
awhile(() => i < 20, () => {
    i = i + 1
    breakwhen(i == 5)
});
println(i)

если вы не хотите ломаться:

awhile(() => i < 20, () => {
    i = i + 1
    breakwhen(false)
});
0 голосов
/ 08 октября 2015

У меня возникла ситуация, подобная приведенному ниже коду

 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.Breaks.break использовал исключение, чтобы разорвать цикл, и это было в блоке catch, поэтому он был перехвачен. 1004 *

У меня есть ужасный способ решить эту проблему: сделать цикл в первый раз и получить счет реальной длины. и использовать его для второго цикла.

вырываться из Скалы не очень хорошо, когда вы используете несколько java-библиотек.

...