Как завершить внешний цикл в вложенных циклах?
Каков наилучший способ для завершения всех вложенных циклов в приведенном ниже примере. Как только инструкция if верна, я хочу закончить внешний оператор for (с I). Другими словами, мне нужно, чтобы весь цикл остановился. Есть ли лучший способ, чем установка я в 10?
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
}
}
Ответы
Ответ 1
Я бы реорганизовал это на метод и просто позвонил return
всякий раз, когда мне нужно.
Вы также можете использовать goto
, а для я используется goto
, но на него нахмурились. Что глупо; этот сценарий , почему он существует на языке.
void DoSomeStuff()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return;
}
}
}
}
...somewhere else...
DoSomeStuff();
Ответ 2
Не стреляйте в меня, но это может на самом деле гарантировать goto:
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something)
goto endOfTheLine;
}
}
}
endOfTheLine:
Console.WriteLine("Pure evilness executed");
Ответ 3
Предполагая, что вы хотите выйти из всех циклов, вы можете реорганизовать его в нечто более структурированное:
bool done = false;
for (int i = 0; i < 10 && !done; i++) {
for (int a = 0; a < 10 && !done; a++) {
for (int b = 0; b < 10 && !done; b++) {
if (something) {
done = true;
continue;
}
}
}
}
Ответ 4
Если тела цикла не производят побочный эффект, а просто ищут первое значение, где "что-то" истинно, тогда проблема будет устранена путем исключения всех петель в первую очередь.
var query = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
where something(I, A, B)
select new { I, A, B };
var result = query.FirstOrDefault();
if (result == null)
{
Console.WriteLine("no result");
}
else
{
Console.WriteLine("The first result matching the predicate was {0} {1} {2},
result.I, result.A, result.B);
}
Но не делайте этого, если петли имеют побочные эффекты; запросы - это действительно плохое место, чтобы поставить побочные эффекты. Если внутренний цикл имеет побочный эффект, вы можете сделать что-то вроде этого:
var triples = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
select new { I, A, B };
foreach(var triple in triples)
{
if (something(triple.I, triple.A, triple.B))
break;
DoSomeSideEffect(triple.I, triple.A, triple.B);
}
и теперь есть только один цикл, чтобы вырваться из него, а не три.
Ответ 5
Почему бы не сделать:
for (int I = 0; I < 10 || !something; I++)
{
for (int A = 0; A < 10 || !something; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
{
I=10;
break;
}
}
}
}
Ответ 6
Вы всегда можете использовать тот факт, что в for
есть условный оператор:
bool working = true;
for (int i=0; i<10 && working; i++)
{
for (int j=0; j<10 && working; j++)
{
for (int k=0; k<10 && working; k++)
{
Console.WriteLine(String.Format("i={0}, j={1}, k={2}", i,j,k));
if (i==5 && j==5 && k==5)
{
working = false;
}
}
}
}
Ответ 7
Я бы склонялся в пользу goto
, кроме того, вам придется выйти из каждого цикла:
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
if (something)
break;
}
if (something)
break;
}
Ответ 8
Если это конечная задача в методе, вы можете вернуться, когда условие истинно.
в противном случае вы должны сделать все значения максимальными значениями
if (something)
{
I=10;
B=10;
A=10;
break;
}
Ответ 9
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something){
B=13;
A=13;
I=13;
}
}
}
}
Очень примитивное решение.
Ответ 10
простое решение состоит в том, чтобы реорганизовать вложенные циклы в отдельный метод с соответствующим типом возвращаемого типа, который вы хотели бы знать в этой точке:
в моем случае я предполагаю, что вы хотели, чтобы значения I, A и B в этой точке были тривиальны с Tuple.
// original method
...
var x = FindFirst()
...
// separate method
public Tuple<int,int,int> FindFirst()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return Tuple.Create(I,A,B);
}
}
}
return null;
}
Если вам нужно передать какое-либо дополнительное состояние методу (для границ или чего-то еще), просто передайте их в качестве параметров.
Если вы хотите обработать неспособность найти первый в другом стиле, то что-то вроде
bool TryFindFirst(out Tuple<int,int,int> x)
будет альтернативой.
В качестве побочного примечания с использованием заглавных букв для имен переменных (особенно однобуквенных) считается слабый стиль в С# (и многих других языках)
Ответ 11
Я не знаю, поддерживает ли C#
, но некоторые языки поддерживают:
break n;
Где n
- количество вложенных циклов, которые нужно сломать.
Ответ 12
Вы всегда можете встретить ожидания циклов:
если (что-то) B = 10
Изменить: (Кажется, вы включили это в свой пост через редактирование)
Если вам не нравится, как он выглядит, вы можете обернуть функцию, например:
Удовлетворить (В, 10)
Затем он выглядит более чистым, но на самом деле не нужен.
Ответ 13
Другая возможность состоит в том, чтобы каскадировать проверку на isSomething во всех для циклов.
вы добавляете
if (something)
break;
во всех 3 циклах
Ответ 14
Лично я бы пошел с методом Paxdiablo выше (+1 для этого), но альтернатива ниже - это зависит от того, должен ли OP знать, что числа I, A и B, когда "что-то" истинно, быть, потому что iab были объявлены в цикле, я предполагаю, что нет.
bool done = false;
int i, a, b;
for (i = 0; i < 10 ; i++) {
for (a = 0; a < 10 ; a++) {
for (b = 0; b < 10 ; b++) {
if (something) {
done = true;
break;
}
}
if (done) break;
}
if (done) break;
}
// i, a and B are set to the last numbers where "something" was true