루프에서 열거 가능한 컬렉션에서 객체를 제거하는 방법 [중복
-
03-07-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
복제하다
열거 가능한 컬렉션 (예 : 사전의 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);
부서지다;
}
물체가 제거 된 다음 루프 출구, 비올라!