¿Cómo rompo un bucle?
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
}
}
¿Cómo convierto los bucles anidados en recursión de cola?
De Scala Talk en FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261 en la página 22:
Romper y continuar Scala no los tiene. ¿Por qué? Son un poco imperativos; utilizar mejor muchas funciones más pequeñas. Emitir cómo interactuar con los cierres. ¡No son necesarios!
¿Cuál es la explicación?
scala
for-loop
break
tail-recursion
TiansHUo
fuente
fuente
i
yj
. Si este código se completa sin salir del bucle, el resultado es que906609
al salir del bucle temprano, el resultado es90909
que romper el bucle no está haciendo que el código sea "más eficiente", ya que está alterando el resultado.Respuestas:
Tienes tres (más o menos) opciones para salir de los bucles.
Suponga que desea sumar números hasta que el total sea mayor que 1000. Intenta
excepto que quieres parar cuando (suma> 1000).
¿Qué hacer? Hay varias opciones
(1a) Use alguna construcción que incluya un condicional que pruebe.
(advertencia: esto depende de los detalles de cómo se intercalan la prueba takeWhile y el foreach durante la evaluación, ¡y probablemente no deberían usarse en la práctica!).
(1b) Use la recursión de cola en lugar de un bucle for, aprovechando lo fácil que es escribir un nuevo método en Scala:
(1c) Vuelva a utilizar un bucle while
(2) Lanzar una excepción.
(2a) En Scala 2.8+, esto ya está preempaquetado en el
scala.util.control.Breaks
uso de sintaxis que se parece mucho a su antiguo descanso familiar de C / Java:(3) Ponga el código en un método y use return.
Esto se hace intencionalmente no demasiado fácil por al menos tres razones en las que puedo pensar. Primero, en bloques de código grandes, es fácil pasar por alto las declaraciones de "continuar" y "romper", o pensar que estás saliendo de más o menos de lo que realmente eres, o que necesitas romper dos bucles que no puedes hacer de todos modos fácilmente, por lo que el uso estándar, aunque práctico, tiene sus problemas y, por lo tanto, debe intentar estructurar su código de una manera diferente. En segundo lugar, Scala tiene todo tipo de anidamientos que probablemente ni siquiera note, por lo que si pudiera salir de las cosas, probablemente se sorprendería de dónde terminó el flujo del código (especialmente con los cierres). Tercero, la mayoría de los "bucles" de Scala no son en realidad bucles normales: son llamadas a métodos que tienen su propio bucle,como un bucle, es difícil encontrar una manera consistente de saber qué debe hacer "break" y cosas similares. Entonces, para ser consistente, lo más sabio es no tener un "descanso" en absoluto.
Nota : Hay equivalentes funcionales de todos estos en los que devuelve el valor en
sum
lugar de mutarlo en su lugar. Estos son Scala más idiomáticos. Sin embargo, la lógica sigue siendo la misma. (sereturn
conviertereturn x
, etc.).fuente
breakable
sección ... y todos esos aros solo para evitar el malbreak
, hmm ;-) Debes admitir que la vida es irónica.break
] Si parece unbreak
ay funciona como unbreak
, en lo que a mí respecta, es unbreak
.Esto ha cambiado en Scala 2.8, que tiene un mecanismo para usar descansos. Ahora puede hacer lo siguiente:
fuente
Nunca es una buena idea salir de un ciclo for. Si está utilizando un bucle for, significa que sabe cuántas veces desea iterar. Use un bucle while con 2 condiciones.
por ejemplo
fuente
Para agregar Rex Kerr responda de otra manera:
(1c) También puedes usar un protector en tu bucle:
fuente
Como todavía no existe
break
en Scala, puede intentar resolver este problema con el uso de unareturn
declaración. Por lo tanto, debe poner su bucle interno en una función; de lo contrario, el retorno omitirá todo el bucle.Scala 2.8 sin embargo incluye una forma de romper
http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html
fuente
use el módulo Break http://www.tutorialspoint.com/scala/scala_break_statement.htm
fuente
Solo usa un ciclo while:
fuente
Un enfoque que genera los valores sobre un rango a medida que iteramos, hasta una condición de ruptura, en lugar de generar primero un rango completo y luego iterar sobre él, usando
Iterator
, (inspirado en el uso de @RexKerr deStream
)fuente
Aquí hay una versión recursiva de la cola. Comparado con las comprensiones, es un poco críptico, lo admito, pero diría que es funcional :)
Como puede ver, la función tr es la contrapartida de las comprensiones externas y tr1 de la interna. De nada si conoce una forma de optimizar mi versión.
fuente
Cerca de su solución sería esto:
La iteración j se realiza sin un nuevo alcance, y la generación del producto y la condición se realizan en la declaración for (no es una buena expresión, no encuentro una mejor). La condición se invierte, lo que es bastante rápido para ese tamaño de problema: tal vez ganes algo con un descanso para bucles más grandes.
String.reverse se convierte implícitamente en RichString, por lo que hago 2 reveses adicionales. :) Un enfoque más matemático podría ser más elegante.
fuente
El
breakable
paquete de terceros es una alternativa posible.https://github.com/erikerlandson/breakable
Código de ejemplo:
fuente
Método básico para romper el ciclo, usando la clase Breaks. Al declarar el bucle como rompible.
fuente
Simplemente podemos hacer en scala es
salida:
fuente
Irónicamente, el allanamiento de Scala
scala.util.control.Breaks
es una excepción:El mejor consejo es: ¡NO use break, continue y goto! En mi opinión, son lo mismo, una mala práctica y una fuente maligna de todo tipo de problemas (y discusiones candentes) y finalmente "se consideran perjudiciales". Bloque de código estructurado, también en este ejemplo los saltos son superfluos. Nuestro Edsger W. Dijkstra † escribió:
fuente
Tengo una situación como el código a continuación
Estoy usando una lib de Java y el mecanismo es que ctx.read produce una excepción cuando no puede encontrar nada. Estaba atrapado en la situación que: tengo que romper el ciclo cuando se lanzó una Excepción, pero scala.util.control.Breaks.break usando Excepción para romper el ciclo, y estaba en el bloque catch, por lo que fue capturado.
Tengo una forma fea de resolver esto: hacer el ciclo por primera vez y obtener el recuento de la longitud real. y úsalo para el segundo ciclo.
sacar un descanso de Scala no es tan bueno cuando estás usando algunas librerías de Java.
fuente
Soy nuevo en Scala, pero ¿qué tal esto para evitar lanzar excepciones y repetir métodos:
úsalo así:
si no quieres romper:
fuente
El uso inteligente del
find
método de recolección hará el truco por usted.fuente
fuente
No sé cuánto ha cambiado el estilo de Scala en los últimos 9 años, pero me pareció interesante que la mayoría de las respuestas existentes usen
vars
o sean difíciles de leer. La clave para salir temprano es usar una colección perezosa para generar sus posibles candidatos, luego verifique la condición por separado. Para generar los productos:Luego, para encontrar el primer palíndromo desde esa vista sin generar todas las combinaciones:
Para encontrar el palíndromo más grande (aunque la pereza no te compra mucho porque tienes que revisar la lista completa de todos modos):
Su código original en realidad está verificando el primer palíndromo que es más grande que un producto posterior, que es lo mismo que verificar el primer palíndromo excepto en una condición límite extraña que no creo que haya querido. Los productos no disminuyen estrictamente monotónicamente. Por ejemplo,
998*998
es mayor que999*997
, pero aparece mucho más tarde en los bucles.De todos modos, la ventaja de la verificación de condición y generación perezosa separada es que la escribes como si usara la lista completa, pero solo genera la cantidad que necesitas. De alguna manera obtienes lo mejor de ambos mundos.
fuente