문제

가 있는 경우 루이 중첩된 내에서 또 다른,어떻게 효율적으로 나오 루프(내부와 외부)에서 가장 빠른 방법이 있을까?

내가 있고 싶지 않을 사용하여 부울 수 있는 말로 가는 또 다른 방법이지만,오히려 다 실행하는 첫 번째 라인의 코드 후 외부 루프입니다.

는 무엇입 빠르고 좋은 방법에 대해 이?

감사


내가 생각하는 예외 없 저렴/해야에 던져 진정으로 뛰어난 상태 등.따라서 나는 생각하지 않는 이 솔루션은 것에서 좋은 성과 관점입니다.

나는 그것을 느끼지 않 그것은 바로 활용하는 새로운 기능.NET(곧 방법)무언가를 하는 이는 매우 기본이다.

그 때문에,tvon(도 있습니다 전 사용자 이름!) 가 좋은 솔루션입니다.

Marc:니스의 사용 곧 방법,그리고 이것은 너무나 할 수 있기 때문에 나는야에서 일을 우리가 사용하지 않습니다.NET/C#을 지원하는 곧 방법을 알아야 하는 전통적인 접근 방식 너무입니다.

도움이 되었습니까?

해결책

잘, goto, 그러나 그것은 못 생겼으며 항상 가능하지는 않습니다. 루프를 메소드 (또는 anon-method)에 넣고 사용할 수도 있습니다. return 기본 코드로 다시 나가려면

    // goto
    for (int i = 0; i < 100; i++)
    {
        for (int j = 0; j < 100; j++)
        {
            goto Foo; // yeuck!
        }
    }
Foo:
    Console.WriteLine("Hi");

VS :

// anon-method
Action work = delegate
{
    for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            return; // exits anon-method
        }
    }
};
work(); // execute anon-method
Console.WriteLine("Hi");

C# 7에서는 "로컬 기능"을 가져와야합니다. 이는 (Syntax TBD 등) 다음과 같은 기능을 수행해야한다는 것을 의미합니다.

// local function (declared **inside** another method)
void Work()
{
    for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            return; // exits local function
        }
    }
};
Work(); // execute local function
Console.WriteLine("Hi");

다른 팁

C# 접근법의 적응 C- 루프 조건 외부의 외부 루프 변수의 세트 값 (예 : int 변수를 사용한 루프 용. INT_MAX -1 종종 좋은 선택입니다) :

for (int i = 0; i < 100; i++)
{
    for (int j = 0; j < 100; j++)
    {
        if (exit_condition)
        {
            // cause the outer loop to break:
            // use i = INT_MAX - 1; otherwise i++ == INT_MIN < 100 and loop will continue 
            i = int.MaxValue - 1;
            Console.WriteLine("Hi");
            // break the inner loop
            break;
        }
    }
    // if you have code in outer loop it will execute after break from inner loop    
}

코드의 참고로 말합니다 break 외부 루프의 다음 반복으로 마술처럼 이동하지 않으므로 내부 루프 외부에 코드가있는 경우이 접근법에는 더 많은 점검이 필요합니다. 그러한 경우 다른 솔루션을 고려하십시오.

이 접근법은 함께 작동합니다 for 그리고 while 루프이지만 작동하지 않습니다 foreach. 경우 foreach 숨겨진 열거 자에 대한 코드에 액세스 할 수 없으므로 변경할 수 없습니다. IEnumerator "movetoend"방법이 없습니다).

상실 된 의견 저자에 대한 감사 :
i = INT_MAX - 1 제안에 의한 제안 메타
for/foreach 댓글 이고.
적절한 IntMax ~에 의해 jmbpiano
내부 루프 후 코드에 대해 언급하십시오 Blizpasta

이 솔루션은 C#에 적용되지 않습니다.

다른 언어를 통해이 질문을 찾은 사람들을 위해 JavaScript, Java 및 D는 레이블이 붙은 휴식을 허용하고 계속합니다.:

outer: while(fn1())
{
   while(fn2())
   {
     if(fn3()) continue outer;
     if(fn4()) break outer;
   }
}

외부 루프에서 적절한 가드를 사용하십시오. 파손되기 전에 안쪽 루프에 가드를 설정하십시오.

bool exitedInner = false;

for (int i = 0; i < N && !exitedInner; ++i) {

    .... some outer loop stuff

    for (int j = 0; j < M; ++j) {

        if (sometest) {
            exitedInner = true;
            break;
        }
    }
    if (!exitedInner) {
       ... more outer loop stuff
    }
}

또는 더 나은 방법은 내부 루프를 메소드로 추상화하고 False를 반환 할 때 외부 루프를 종료하십시오.

for (int i = 0; i < N; ++i) {

    .... some outer loop stuff

    if (!doInner(i, N, M)) {
       break;
    }

    ... more outer loop stuff
}

이것에 대해 나를 인용하지 말고 당신은 사용할 수 있습니다 이동 MSDN에서 제안한 바와 같이. 두 루프의 각 반복에서 확인되는 플래그를 포함하여 다른 솔루션이 있습니다. 마지막으로 문제에 대한 헤비급 솔루션으로 예외를 사용할 수 있습니다.

이동:

for ( int i = 0; i < 10; ++i ) {
   for ( int j = 0; j < 10; ++j ) {
      // code
      if ( break_condition ) goto End;
      // more code
   }
}
End: ;

상태:

bool exit = false;
for ( int i = 0; i < 10 && !exit; ++i ) {
   for ( int j = 0; j < 10 && !exit; ++j ) {
      // code
      if ( break_condition ) {
         exit = true;
         break; // or continue
      }
      // more code
   }
}

예외:

try {
    for ( int i = 0; i < 10 && !exit; ++i ) {
       for ( int j = 0; j < 10 && !exit; ++j ) {
          // code
          if ( break_condition ) {
             throw new Exception()
          }
          // more code
       }
    }
catch ( Exception e ) {}

루프를 위해 중첩을 비공개 방법으로 리팩터 할 수 있습니까? 그렇게하면 루프를 종료하기 위해 방법에서 '반환'할 수 있습니다.

그것은 나 같은 사람이 싫어하는 goto 문의를 많이,그래서 나는 할 필요를 느꼈을 곧게 이것은 비트입니다.

내가 믿고'정'에 대한 사람들 goto 결국 졸의 코드에 대한 이해 및(오해)에 대한 가능한 성능을 의미를 갖는다.질문에 대답하기 전에,나는 것입니다 따라서 첫 번째로 갈 일부 세부 사항을 어떻게 그것을 컴파일합니다.

우리 모두 알고,C#컴파일하 IL 는 다음을 컴파일을 어셈블러를 사용하여 SSA 컴파일러입니다.나는 조금의 대한 통찰력 어떻게 이 모든 작업,그리고 다음 질문에 답변하기 위해 노력하십시오 자체입니다.

C#IL

먼저 우리는 필요한 조각 C#의 코드입니다.시작하자 간단하다:

foreach (var item in array)
{
    // ... 
    break;
    // ...
}

내가 이렇게 단계별로 당신의 좋은 아이디어에서 발생합니다.

첫 번역:서 foreach 에 해당하는 for 루프(주의:나는 배열을 사용하기 때문에,여기에 나가고 싶지 않으로의 세부 사항 IDisposable--어떤 경우에도를 사용해야는 폐쇄):

for (int i=0; i<array.Length; ++i)
{
    var item = array[i];
    // ...
    break;
    // ...
}

두 번째로 번역:이 forbreak 번역으로 쉽게에 해당:

int i=0;
while (i < array.Length)
{
    var item = array[i];
    // ...
    break;
    // ...
    ++i;
}

고 세 번역(이하 상당의 IL 코드):우리는 변화 breakwhile 로점:

    int i=0; // for initialization

startLoop:
    if (i >= array.Length) // for condition
    {
        goto exitLoop;
    }
    var item = array[i];
    // ...
    goto exitLoop; // break
    // ...
    ++i;           // for post-expression
    goto startLoop; 

는 컴파일러는 이러한 것들을 단일 단계에서,그것은 당신에게 통찰력을 제공합 과정이다.IL 코드 진화하는 C#프로그램 의 마지막 C#코드입니다.당신이 볼 수 있습니다 자신을 위해 여기: https://dotnetfiddle.net/QaiLRz (보기'를 클릭하면 IL')

이제 한 가지 당신을 관찰하는 프로세스 동안,코드가 더 복잡합니다.가장 쉬운 방법을 관찰하는 이 사실에 의해 우리가 필요한 더 많은 코드를 ackomplish 같은 것입니다.수도 있습니다 주장한 foreach, for, whilebreak 실제로 짧은 손해 goto, 는 부분적으로 진리입니다.

IL 을 어셈블러

니다.NET JIT 컴파일러입니다 SSA 컴파일러입니다.내가 가지 않을 것으로의 모든 세부 사항 SSA 양식을 여기를 만드는 방법을 최적화하는 컴파일러,그것은 너무 많은,하지만 줄 수 있는 기본적인 이해에 대해 무엇이 일어날 것입니다.에 대한 깊은 이해,그것은 최고의 읽기 시작하에 최적화하는 컴파일러(저는 이 책에 대한 간략한 소개: http://ssabook.gforge.inria.fr/latest/book.pdf 다)및 LLVM(llvm.org).

매 최적화하는 컴파일러에 의존한다는 사실은 코드 다음 예측 가능한 패턴.의 경우 루,우리가 사용하는 그래프 이론을 지점 분석한 다음 최적화 같은 것들 cycli 에서 우리의 가지(예를들면뒤로 가지).

그러나 지금 우리가 앞으로 가지를 구현하는 우리의 루프가 있습니다.짐작할 수 있겠지만,이것은 실제로 중 하나의 첫 번째 단계를 JIT 을 수정은 다음과 같습니다.

    int i=0; // for initialization

    if (i >= array.Length) // for condition
    {
        goto endOfLoop;
    }

startLoop:
    var item = array[i];
    // ...
    goto endOfLoop; // break
    // ...
    ++i;           // for post-expression

    if (i >= array.Length) // for condition
    {
        goto startLoop;
    }

endOfLoop:
    // ...

당신이 볼 수 있듯이,우리는 지금 이전 버전 분기는 우리의 작은 루프입니다.는 유일한 것은 아직도 불쾌한 여기에 있는 분기를 우리는 결국 때문에 우리의 break 문입니다.어떤 경우에,우리는 이동할 수 있는 이와 같은 방법이지만,그것은 다른 사람의가 있을겁니다.

왜 컴파일러가 이렇게 할까요?음,우리가 할 수 있습 풀 반복할 수 있는 방법을 알게 될 수도 있을 벡터화니다.우리는 할 수 있는 증거가있다 상수가 추가되는 것을 의미 우리의 루프 전체할 수 있으로 사라져 공입니다.요약하면 다음과 같습니다.하여 패턴을 예측(하여 분기 예측),우리가 할 수 있는 증거는 특정 조건에서 우리의 반복을 의미하는,우리가 할 수 있는 마법의 동안 JIT 최적화입니다.

그러나,가지 경향이 그 좋은 예측 가능한 패턴,는 무언가를 최적화 따라서류-은 싫어합니다.휴식,계속 고토-그들은 모든 중단하려는 이러한 예측 가능한 패턴-하며 따라서 정말 좋다'.

당신은 또한 깨닫게 이 시점에서는 간단한 foreach 예측 가능한 다음의 무리 goto 문는 가서 모든 장소입니다.의 측면에서(1)읽고(2)에서 최적화 관점,그것은 모두의 더 나은 솔루션입니다.

다른 것은 언급 할 가치가있는 것은 매우 관련 최적화를 위한 컴파일러를 할당하는 레지스터 변수(라는 프로세스 등록 할당).당신이 알고 있습니다,거기에만 한정된 수의 레지스터에 CPU 그리고 그들은 지금까지 가장 빠른의 조각을 메모리에서 하드웨어입니다.에 사용되는 변수는 코드에서 대부분의 루프가를 얻기 위하여 확률이 높다는 것에 등록이 할당되는 변수의 외부 루프는 덜 중요(기 때문에 이 코드는 아마 히트 이하).

도움말 너무 복잡...나는 무엇을 해야 합니까?

결론은 당신은 항상 사용할 언어를 구성한 귀하의 처분에 있는 일반적으로(implictly)구조 예측 가능한 패턴에 대한 귀하의 컴파일러입니다.을 피하려고 이상한 가지 가능한 경우(특히: break, continue, gotoreturn 의 중간에서 아무것도).

좋은 소식은 여기에는 이러한 예측 가능한 패턴의 모두에 쉽게 읽기(인간)하고 쉽게(를 위한 컴파일러).

중 하나는 사람들이라고 세세 뜻하는 단 하나의 종료됩니다.

그리고 지금 우리가 진짜 질문입니다.

상상해 뭔가를 가지고 있는 다음과 같다:

// a is a variable.

for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j)
  {
     // ...

     if (i*j > a) 
     {
        // break everything
     }
  }
}

가장 쉬운 방법을 만들이 예측 가능한 패턴을 단순히 제거 if 완전히:

int i, j;
for (i=0; i<100 && i*j <= a; ++i) 
{
  for (j=0; j<100 && i*j <= a; ++j)
  {
     // ...
  }
}

다른 경우에 당신은 또한 분할 방법에는 2 가지 방법:

// Outer loop in method 1:

for (i=0; i<100 && processInner(i); ++i) 
{
}

private bool processInner(int i)
{
  int j;
  for (j=0; j<100 && i*j <= a; ++j)
  {
     // ...
  }
  return i*j<=a;
}

임시 변수가?좋은 나쁜 추?

수도 결정을 반환하는 부울에서 반복(그러나 저는 개인적으로 선호하는 세세 양식 때문에 그 방법을 컴파일러에 이를 보고 나는 생각을 읽).

어떤 사람들은 생각하기를 사용하여 일시적 변수,그리고 솔루션을 제안하고 다음과 같다:

bool more = true;
for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j) 
  {
     // ...
     if (i*j > a) { more = false; break; } // yuck.
     // ...
  }
  if (!more) { break; } // yuck.
  // ...
}
// ...

나는 개인적으로 반대되는 것이다.다시보는 방법에 코드를 컴파일합니다.이제에 대한 생각이 무엇을 할 것으로 이 좋은 예측 가능한 패턴이 있습니다.그림을 얻는가?

바로,그것을 밖으로 철자가 보자.무슨 일이 일어날 것이다:

  • 컴파일러를 쓸 것이 밖으로 모든 것을 가지입니다.
  • 으로 최적화 단계,컴파일러지 데이터 흐름 분석을 제거하려고 하는 이상한 more 변수만 발생하는 것에 사용되는 제어 흐름입니다.
  • 는 경우는 성공적인 변수 more 제거 될 것입니다 프로그램에서만 가지 남아 있습니다.이러 가지 최적화됩니다,그래서 당신을 얻을 것이 하나만점의 밖으로 내부 반복입니다.
  • 는 경우에 실패할 변수 more 은 확실히 사용에서 가장 안쪽 반복,그렇게 컴파일러가지 최적화하다,그것은 높은 기회를 할당하여 등록(는 먹는 귀중한 등록 memory).

그래서 요약하면 다음과 같습니다.최적화 프로그램에서 귀하의 컴파일러으로 갈 것이 많은 지옥의 문제를 파악하는 more 만 사용에 대한 통제 흐름 및 에서 최고의 경우 시나리오 번역의 단일 지점은 외부의 외부를 위한 루프입니다.

다시 말해서,최고의 경우 시나리오는 그것으로 끝날 것이 상당의 이:

for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j)
  {
     // ...
     if (i*j > a) { goto exitLoop; } // perhaps add a comment
     // ...
  }
  // ...
}
exitLoop:

// ...

나 개인적인 의견에 이것은 매우 간단하다:이것이 우리가 무엇을 의도된 모두 함께,의 세계를 쉽게 확인 모두에 대한 컴파일러와 읽고 쓰는니다.

tl;박사:

Bottom line:

  • 간단한 사용 조건에서 귀하에 대한 반복하면 가능합니다.지팡이 높은 수준의 언어 구조를 당신이 당신의 처리에있는만큼 가능합니다.
  • 는 경우에는 모두가 실패하고 당신은 왼쪽으로 중 gotobool more, 을 선호하였습니다.

함수/방법을 고려하고 조기 반환을 사용하거나 루프를 while-clase로 재 배열하십시오. Goto/Extrections/여기서 적절하지 않은 것은 무엇이든.

def do_until_equal():
  foreach a:
    foreach b:
      if a==b: return

당신은 빠르고, 좋은, 부울 사용, goto 사용 및 c#의 조합을 요청했습니다. 당신은 당신이 원하는 것을하는 모든 가능한 방법을 배제했습니다.

가장 빠르고 가장 못생긴 방법은 Goto를 사용하는 것입니다.

때로는 코드를 자신의 기능으로 추상화하는 것이 좋으며 조기 반환을 사용하는 것보다 초기 반환은 악합니다.

public void GetIndexOf(Transform transform, out int outX, out int outY)
{
    outX = -1;
    outY = -1;

    for (int x = 0; x < Columns.Length; x++)
    {
        var column = Columns[x];

        for (int y = 0; y < column.Transforms.Length; y++)
        {
            if(column.Transforms[y] == transform)
            {
                outX = x;
                outY = y;

                return;
            }
        }
    }
}

상황에 따라 내부 루프 이후 코드를 실행하지 않는 경우에만이를 수행 할 수 있습니다.

for (int i = 0; i < 100; i++)
{
    for (int j = 0; j < 100; j++)
    {
        i = 100;
        break;
    }
}

우아하지는 않지만 문제에 따라 가장 쉬운 솔루션 일 수 있습니다.

나는 "break"를 사용하는 많은 예를 보았지만 "계속"을 사용하는 것은 없었습니다.

여전히 내부 루프에 어떤 종류의 플래그가 필요합니다.

while( some_condition )
{
    // outer loop stuff
    ...

    bool get_out = false;
    for(...)
    {
        // inner loop stuff
        ...

        get_out = true;
        break;
    }

    if( get_out )
    {
        some_condition=false;
        continue;
    }

    // more out loop stuff
    ...

}

내가 처음 본 이후 break 수십 년 전 C 에서이 문제가 저를 맹세했습니다. 나는 언어 향상이 다음에 효과가있는 확장을 원한다고 희망했다.

break; // our trusty friend, breaks out of current looping construct.
break 2; // breaks out of the current and it's parent looping construct.
break 3; // breaks out of 3 looping constructs.
break all; // totally decimates any looping constructs in force.

나는 학생 시절부터 수학적으로 입증 된 것이 당신이 goto없이 코드로 무엇이든 할 수 있다는 것을 기억했습니다 (즉, Goto가 유일한 대답 인 상황은 없습니다). 그래서 나는 GoTo를 사용하지 않습니다 (내 개인적인 취향, 내가 옳고 그름을 제안하지는 않습니다)

어쨌든, 중첩 된 루프에서 벗어나려면 다음과 같은 일을합니다.

var isDone = false;
for (var x in collectionX) {
    for (var y in collectionY) {
        for (var z in collectionZ) {
            if (conditionMet) {
                // some code
                isDone = true;
            }
            if (isDone)
                break;
        }
        if (isDone) 
            break;
    }
    if (isDone)
        break;
}

... 나를 좋아하는 사람들에게 도움이되기를 바랍니다.

그것이 내가 한 방식입니다. 여전히 해결 방법입니다.

foreach (var substring in substrings) {
  //To be used to break from 1st loop.
  int breaker=1;
  foreach (char c in substring) {
    if (char.IsLetter(c)) {
      Console.WriteLine(line.IndexOf(c));
      \\setting condition to break from 1st loop.
      breaker=9;
      break;
    }
  }
  if (breaker==9) {
    break;
  }
}

외계인 루프가 나오는 사용자 정의 예외를 던지십시오.

그것은 작동합니다 for,foreach 또는 while 또는 모든 종류의 루프 및 사용하는 언어 try catch exception 차단하다

try 
{
   foreach (object o in list)
   {
      foreach (object another in otherList)
      {
         // ... some stuff here
         if (condition)
         {
            throw new CustomExcpetion();
         }
      }
   }
}
catch (CustomException)
{
   // log 
}
         bool breakInnerLoop=false
        for(int i=0;i<=10;i++)
        {
          for(int J=0;i<=10;i++)
          {
              if(i<=j)
                {
                    breakInnerLoop=true;
                    break;
                }
          }
            if(breakInnerLoop)
            {
            continue
            }
        }

내가 당신이 그 사람이 당신의 진술을 언급하는 대답을 받아 들였습니다. 이 시점에서 질문의 해결책은 매우 간단합니다. 이런 종류의 시나리오에서 부울 깃발을 사용할 수 있습니다.

            for (; j < 10; j++)
            {
                //solution
                bool breakme = false;
                for (int k = 1; k < 10; k++)
                {
                   //place the condition where you want to stop it
                    if ()
                    {
                        breakme = true;
                        break;
                    }
                }

                if(breakme)
                    break;
               }

단순하고 평범한. :)

당신은 심지어 보았습니까? break 예어? 우

이것은 단지 의사 코드이지만, 내가 의미하는 바를 볼 수 있어야합니다.

<?php
for(...) {
    while(...) {
        foreach(...) {
            break 3;
        }
    }
}

당신이 생각한다면 break 기능과 같은 기능 break(), 그러면 매개 변수는 나올 루프의 수입니다. 우리가 여기 코드의 세 번째 루프에있을 때, 우리는 세 가지 모두에서 벗어날 수 있습니다.

수동: http://php.net/break

나는 당신이 "부울 일"을하고 싶지 않다면 실제로 유일한 해결책은 실제로 던지는 것입니다. 분명히하지 말아야 할 것 ..!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top