Как мне разорвать петлю?
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-й странице:
Разбить и продолжить у Скалы их нет. Зачем? Они немного необходимы; лучше использовать множество мелких функций. Вопрос о том, как взаимодействовать с замыканиями. Они не нужны!
Какое объяснение?
scala
for-loop
break
tail-recursion
TiansHUo
источник
источник
i
иj
. Если этот код выполняется до завершения, не выходя из цикла, то результат заключается906609
в том, что преждевременный выход из цикла приводит к90909
тому, что выход из цикла не делает код «более эффективным», поскольку он изменяет результат.Ответы:
У вас есть три (или около того) варианта вырваться из петель.
Предположим, вы хотите суммировать числа, пока сумма не станет больше 1000. Вы пытаетесь
кроме того, что вы хотите остановить, когда (сумма> 1000).
Что делать? Есть несколько вариантов.
(1a) Используйте некоторую конструкцию, включающую проверяемое условие.
(предупреждение - это зависит от деталей того, как тест takeWhile и foreach чередуются во время оценки, и, вероятно, не должны использоваться на практике!).
(1b) Используйте хвостовую рекурсию вместо цикла for, используя преимущества того, как легко написать новый метод в Scala:
(1c) Возврат к использованию цикла while
(2) Брось исключение.
(2a) В Scala 2.8+ это уже предварительно упаковано с
scala.util.control.Breaks
использованием синтаксиса, который очень похож на ваш знакомый старый перерыв в C / Java:(3) Поместите код в метод и используйте return.
Это намеренно сделано не слишком легко по крайней мере по трем причинам, которые я могу придумать. Во-первых, в больших блоках кода легко пропустить операторы «continue» и «break», или думать, что вы выбиваете больше или меньше, чем вы есть на самом деле, или вам нужно разбить два цикла, которые вы не можете сделать в любом случае это легко - поэтому стандартное использование, хотя и удобно, имеет свои проблемы, и поэтому вы должны попытаться структурировать свой код по-другому. Во-вторых, в Scala есть все виды вложений, которые вы, вероятно, даже не замечаете, поэтому, если вы можете разорвать все вокруг, вы, вероятно, будете удивлены тем, где закончился поток кода (особенно с замыканиями). В-третьих, большинство «циклов» Scala на самом деле не являются обычными циклами - это вызовы методов, которые имеют свой собственный цикл,петлеобразно, трудно придумать последовательный способ узнать, что должен делать «перерыв» и тому подобное. Поэтому, чтобы быть последовательным, разумнее всего не иметь «перерыва».
Примечание : есть функциональные эквиваленты всех этих, где вы возвращаете значение,
sum
а не изменяете его на месте. Это более идиоматические Scala. Однако логика остается прежней. (return
становитсяreturn x
и т. д.).источник
breakable
раздел ... и все эти обручи, чтобы избежать злаbreak
, хм ;-) Согласись, жизнь иронична.break
], если она выглядит как abreak
и выполняет какbreak
, насколько я понимаю, этоbreak
.Это изменилось в Scala 2.8, в которой есть механизм для использования разрывов. Теперь вы можете сделать следующее:
источник
Это никогда не хорошая идея, чтобы выйти из цикла. Если вы используете цикл for, это означает, что вы знаете, сколько раз вы хотите выполнить итерацию. Используйте цикл с 2 условиями.
например
источник
Чтобы добавить Rex Kerr, ответьте по-другому:
(1c) Вы также можете использовать охрану в своей петле:
источник
Поскольку
break
в Scala его еще нет, вы можете попытаться решить эту проблему с помощьюreturn
-statement. Поэтому вам нужно поместить свой внутренний цикл в функцию, иначе возврат пропустит весь цикл.Scala 2.8, однако, включает в себя способ сломаться
http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html
источник
использовать модуль разрыва http://www.tutorialspoint.com/scala/scala_break_statement.htm
источник
Просто используйте цикл while:
источник
Подход, который генерирует значения в диапазоне во время итерации, вплоть до нарушающего условия, вместо генерации сначала всего диапазона, а затем итерации по нему с использованием
Iterator
(вдохновлено использованием @RexKerrStream
)источник
Вот хвостовая рекурсивная версия. По сравнению с «для понимания» это немного загадочно, правда, но я бы сказал, его функционал :)
Как видите, функция tr является аналогом внешнего понимания и tr1 внутреннего. Не за что, если вы знаете способ оптимизировать мою версию.
источник
Близко к вашему решению было бы это:
J-итерация выполняется без новой области видимости, а генерация продукта, а также условие выполняются в операторе for (не очень хорошее выражение - лучшего я не нахожу). Условие меняется на противоположное, что довольно быстро для такого размера задачи - возможно, вы получите что-то с разрывом для больших циклов.
String.reverse неявно преобразуется в RichString, поэтому я делаю 2 дополнительных реверса. :) Более математический подход может быть более элегантным.
источник
Сторонний
breakable
пакет является одной из возможных альтернативhttps://github.com/erikerlandson/breakable
Пример кода:
источник
Основной метод для разрыва цикла, используя класс Breaks. Объявляя цикл как разрушаемый.
источник
Просто мы можем сделать в Скала
вывод :
источник
По иронии судьбы, взлом Scala
scala.util.control.Breaks
является исключением:Лучший совет: НЕ используйте перерыв, продолжайте и переходите! ИМО - это то же самое, плохая практика и злой источник всех видов проблем (и горячих дискуссий) и, наконец, «считается вредным». Блок кода структурирован, также в этом примере разрывы излишни. Наш Эдсгер В. Дейкстра † писал:
источник
Я получил ситуацию, как код ниже
Я использую Java-библиотеку, и механизм заключается в том, что ctx.read создает исключение, когда ничего не может найти. Я попал в ситуацию, в которой: я должен был разорвать цикл, когда было сгенерировано исключение, но scala.util.control.Breaks.break использовал исключение, чтобы разорвать цикл, и это было в блоке catch, таким образом, он был перехвачен.
Я получил ужасный способ решить эту проблему: сделать цикл в первый раз и получить счет реальной длины. и использовать его для второго цикла.
Отрываться от Скалы не очень хорошо, когда вы используете некоторые java-библиотеки.
источник
Я новичок в Scala, но как насчет этого, чтобы избежать создания исключений и повторения методов:
используйте это так:
если не хочешь ломаться
источник
Умное использование
find
метода для сбора поможет вам.источник
источник
Я не знаю, насколько сильно изменился стиль Scala за последние 9 лет, но мне было интересно, что большинство существующих ответов используют
vars
или трудно читаемую рекурсию. Ключом к раннему выходу является использование ленивого набора для генерации возможных кандидатов, а затем проверка состояния отдельно. Для создания продуктов:Затем, чтобы найти первый палиндром из этого представления без генерации каждой комбинации:
Чтобы найти самый большой палиндром (хотя лень не стоит вам много, потому что вы все равно должны проверить весь список):
Ваш исходный код фактически проверяет первый палиндром, который больше, чем последующий продукт, что аналогично проверке первого палиндрома, за исключением странного граничного условия, которое, я думаю, вы не предполагали. Продукты не являются строго монотонно убывающими. Например,
998*998
больше чем999*997
, но появляется намного позже в циклах.В любом случае, преимущество раздельной проверки ленивости и условий заключается в том, что вы пишете ее почти так же, как и весь список, но она генерирует столько, сколько вам нужно. Вы как бы получаете лучшее из обоих миров.
источник