문제

복제하다

반복하는 동안 컬렉션을 수정합니다


열거 가능한 컬렉션 (예 : 사전의 ILIST 또는 KeyValuePairs)을 통해 반복하는 동안 물체를 제거 할 수 없게 될 수있는 좋은 패턴이 있습니까?

예를 들어, Foreach 동안 열거되는 목록을 수정하므로 다음은 실패합니다.

foreach (MyObject myObject in MyListOfMyObjects)
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

과거에는 두 가지 방법을 사용했습니다.

Foreach를 반전 된 루프로 교체했습니다 (객체를 제거하면 반복되는 색인을 변경하지 않도록).

또한 루프 내부에서 제거 할 새로운 객체 모음을 저장 한 다음 해당 컬렉션을 통해 루프를하고 원래 컬렉션에서 객체를 제거했습니다.

이것들은 잘 작동하지만 둘 다 느낌 좋아, 그리고 누군가 더 많은 것을 생각해 냈는지 궁금해 우아한 문제에 대한 해결책

도움이 되었습니까?

해결책

유용합니다 List<T>.RemoveAll(Predicate<T> match) 내가 생각하는 방법은 이것을 위해 설계되었다고 생각합니다. http://msdn.microsoft.com/en-us/library/wdka673a.aspx

다른 팁

간단한 생각이지만 ienumerable/ilist에서 항목을 삭제하려고 할 때는 보통 사본을 만듭니다.

foreach (MyObject myObject in new List<MyObject>(MyListOfMyObjects))
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

가장 효율적인 방법은 아니지만 읽기 쉽습니다. 조기 최적화 및 그 모든 것.

반대로 수행하여 새 목록을 작성하십시오.

List myFilteredList = new List();
foreach (MyObject myObject in myListOfMyObjects)
{
     if (!condition) myFilteredList.Add(myObject);
}

그런 다음 필요한 곳마다 새 목록을 사용하십시오.

LINQ 표현식을 쉽게 사용하여 조건을 반전시킬 수도 있습니다. 이것은 새로운 구조를 만들지 않는다는 이점이 추가되었지만 게으른 열거 가능한 함정의 함정도 다음과 같습니다.

var myFilteredList = from myObject in myListOfMyObjects
                     where !condition
                     select myObject;

그러나 목록에서 항목을 진정으로 제거 해야하는 경우 일반적으로 "새 목록을 작성한 다음 반복 및 제거"접근 방식을 사용합니다.

방금이 게시물을 발견했고 공유 할 것이라고 생각했습니다.

void RemoveAll(object condition)  
{

    bool found = false;

    foreach(object thisObject in objects)    
    {

        if (condition)    
        {    
            objects.Remove(thisObject);

            found = true;

            break; //exit loop    
        }     
     }

    // Call again recursively

    if (found) RemoveAll(condition);

}

루프 아이디어 반전이 마음에 들지 않습니다. 특정 데이터 구조에서만 작동하기 때문입니다.

일반적으로 두 번째 기술을 사용하고 별도의 '삭제 된'컬렉션으로 삭제할 항목을 축적합니다. 삭제로 인해 기존 반복이 무효화 될 수 있다면 (예를 들어 균형 잡힌 트리 컬렉션에서 발생할 것입니다)이 주위의 방법은 보이지 않습니다.

내가 때때로 사용했던 유일한 다른 기술은 삭제해야 할 첫 번째 요소를 찾을 때 전체 반복을 다시 시작하는 것입니다. 삭제할 항목을 찾지 않고 사용하면 기능이 완료됩니다. 이는 비효율적이지만 컬렉션에서 하나의 항목을 삭제하면 삭제 해야하는 항목 세트가 변경 될 수 있습니다.

사전이 있고 모든 값을 처분하고 싶습니다. 각 값이 배치되면 사전에서 스스로를 제거하여 논의하는 문제가 발생합니다. 나는 다음을했다 :

foreach (var o in dictionary.Values.ToList())
{
  o.Dispose();
}

나는 이것이 지금 죽었을 수도 있지만 항상 그렇게하는 방식은 다음과 같습니다.

foreach (myobject myobject in mylistofmyobjects)
{

if (조건) mylistofmyObjects.remove (myObject);

부서지다;

}

물체가 제거 된 다음 루프 출구, 비올라!

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