2011-12-11 5 views
2

이 csharp 코드를보고 목록에서 항목을 찾아 삭제 한 후 루프를 종료해야하는 이유를 알 수 있는지 확인하십시오. 아이디어는 노드의 이웃 목록을 통해 노드 n이 있는지 확인한 다음 해당 이웃을 삭제하는 것입니다.foreach 루프에서 노드 삭제

internal void RemoveDirected(Node n) 
    { 
     foreach (EdgeToNeighbor etn in this.Neighbors) 
     { 
      if (etn.Neighbor.Key == n.Key) 
      { 
       RemoveDirected(etn); 
       break; 
      } 
     } 
    } 

    internal void RemoveDirected(EdgeToNeighbor e) 
    { 
     Neighbors.Remove(e); 
    } 

. . .

// Removes EdgeToNeighbor instance from AdjacencyList 
    protected internal virtual void Remove(EdgeToNeighbor e) 
    { 
     base.InnerList.Remove(e); 
    } 

첫 번째 방법에서 RemoveDirected 호출 후 "휴식"방법을 유의하십시오. 나는 RemoveDirected 후에 종료하지 않으면 foreach 루프에서 영원히 계속 될 것이라고 발견했습니다. 나는 그것이 foreach가 작동하는 방법과 관련이있는 이 있어야한다고 생각합니다. foreach가 작동하는 목록을 수정하면 혼동을 일으키고 계속 반복됩니다.

이 유형의 것을 보았으며 break를 사용하는 대신 사용할 다른 옵션은 무엇입니까? 물론 로컬 변수에서 찾은 노드를 루프에서 분리하고 루프 외부에서 삭제할 수 있습니다. 그러나 나는 생각하고있다, 이것을 할 수있는 더 좋은 방법이있을 수있다. csharp.

+0

의견을 보내 주셔서 감사합니다. 제가 한 번 해보고 싶은 것은 여러분이 제안하고있는 해결책을위한 코드를 제공해주십시오. 코드 예제를 통해 확실히 추천할만한 내용을 명확하게 나타낼 수 있습니다. 미리 감사드립니다. –

답변

0

노드 수를 얻은 다음 for 루프에서 가장 높은 값에서 가장 낮은 값까지 확인하고 삭제하여 더 이상 존재하지 않는 항목을 찾지 않아도됩니다.

+0

내가 제안하는 코드 예제를 제공 할 수 있다면 크게 감사하겠습니다. –

+0

@FoRum competent_tech의 답변을 아래에서 확인하십시오. –

8

iterator를 사용하여 .NET 컬렉션을 반복 할 때 해당 컬렉션을 수정하면 안됩니다. 그렇게한다면, 문제를 요구하고 있습니다.

foreach 루프에서 삭제하는 대신 삭제를 지연해야합니다. 예를 들어, 목록에서 삭제해야하는 모든 항목을 수집 한 다음 foreach 외부의 항목을 삭제할 수 있습니다.

var toDelete = this.Neighbors.Where(etn => etn.Neighbor.Key == n.Key).ToList(); 
foreach (var e in toDelete) { 
    Neighbors.Remove(e); 
} 
+0

이것은 어리석은 것처럼 보입니다. 제거 대상 목록을 만드는 곳 : P ~ –

+0

@pst 왜? 이 코드는 일반 영어와 거의 비슷하기 때문에 누구나 읽을 수 있도록 의도를 전달합니다. 나에게 이것은 최적화 된 것을 수행하여 잠재적으로 절약 할 수있는 CPU주기보다 훨씬 더 중요합니다. – dasblinkenlight

+0

Where *가 * 필터이기 때문에 어리석은 것처럼 보입니다. 다른 부작용 코드가 있다면 그렇습니다. 때로는이 접근법을 사용합니다 ... 그러나 이와 같은 경우는 아닙니다.(나는 이웃들이 * 공유되지 않는다고 추측하지만 그것은 항상 내 코드에서 유효한 더 큰 가정이다.) –

1

항목을 제거하는 경우에는 반복기를 사용하지 않으셔도됩니다. 하나의 옵션은 아래 계산 루프로 변경하는 것입니다 : 당신은 또한 당신의 반복을 완료 한 후 삭제를 수행 한 후 루프 내 컬렉션의 삭제할 키 또는 항목을 수집하고 수

for (int nI = this.Neighbors.Count; nI >= 0; nI--) 
    { 
     var etn = this.Neighbors[nI]; 
     if (etn.Neighbor.Key == n.Key) 
     { 
      RemoveDirected(n); 
     } 
    } 

.

그러나 단 하나의 항목 만 제거하고 컬렉션의 항목이 어떻게 든 키 입력되면 실제로 루프가 필요하지 않습니다. 컬렉션에있는 키 또는 항목의 존재를 테스트하고, 해당 항목이 있으면 제거하십시오.

관련 문제