Как завершить внешний цикл в вложенных циклах?

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