2008-11-21 3 views
37

데이터 테이블에서 일부 행을 삭제해야합니다. 컬렉션을 반복하면서 컬렉션을 변경하는 것이 좋지 않다고 들었습니다. 따라서 for 루프 대신에 행이 삭제 요구 사항을 충족하는지 확인한 다음 삭제 된 것으로 표시해야합니다. 먼저 데이터 테이블을 반복하고 목록의 모든 행을 추가 한 다음 목록을 반복하고 표시해야합니다 삭제를위한 행. 이것에 대한 이유는 무엇이며, (내가 말하는 행 목록을 사용하는 대신) 어떤 대안을 사용할 수 있습니까?C에서 iterating 동안 열거 형 컬렉션에서 항목을 수정하거나 삭제하는 방법

+0

이 질문을 쉽게 찾을 수 있도록 제목을 편집했습니다. 이전에 폐쇄 한 속임수가 있었지만 사용자가 이전 제목으로이 질문을 놓친 모양을 알 수 있습니다. –

답변

17

간단한 for 루프를 사용하면 컬렉션에서 요소를 제거 할 수 있습니다. 루프이 처리 할 동안

 var l = new List<int>(); 

     l.Add(0); 
     l.Add(1); 
     l.Add(2); 
     l.Add(3); 
     l.Add(4); 
     l.Add(5); 
     l.Add(6); 

     for (int i = 0; i < l.Count; i++) 
     { 
      if (l[i] % 2 == 0) 
      { 
       l.RemoveAt(i); 
       i--; 
      } 
     } 

     foreach (var i in l) 
     { 
      Console.WriteLine(i); 
     } 
+4

모든 요소가 검사되는 것은 아니므로 이는 결함이 있습니다. i에서 요소를 제거하면 i + 1에있는 요소가 i가됩니다. 다음 루프에 대해 i가 증가하면 제거 된 요소를 바꾼 요소를 건너 뜁니다 (의미가 있기를 바랍니다). –

+1

이 문제를 해결했습니다. 때 리고 Andy에게 고마워. 그러나 제 요점은 for 루프를 사용하여 콜렉션을 변경할 수 있다는 것입니다. –

+0

removeat가 업데이트 절차에서 테이블 어댑터에 문제를 발생시킬 수 있으므로 l [i] .Delete()를 사용할 수 있습니까 (행은 삭제 된 것으로 표시되는 대신 테이블에서 제거됩니다). – kjv

3

A : :

int i = 0; 
while(i < list.Count) 
{ 
    if(<codition for removing element met>) 
    { 
     list.RemoveAt(i); 
    } 
    else 
    { 
     i++; 
    } 
} 
+0

이 솔루션은 위와 동일한 문제에 직면 해 있습니다. 항목을 삭제하면 색인이 해제됩니다. – Element

+2

아니요 요소가 제거되지 않은 경우에만 색인이 증가합니다. –

2

삭제 또는 그것을 깰 수를 통해 당신이 말한 것처럼, 반복 동안 목록에 추가

이 예에서 살펴 보자.

당신이 DataTable의 작업 및 테이블 어댑터를 다시 서버에 변경 사항을 지속 할 수 있어야하고 있기 때문에
ArrayList matches = new ArrayList(); //second list 

for MyObject obj in my_list 
{ 

    if (obj.property == value_i_care_about) 
     matches.addLast(obj); 
} 

//now modify 

for MyObject m in matches 
{ 
    my_list.remove(m); //use second list to delete from first list 
} 

//finished. 
+0

이 방법은 실제로 스레드 안전성이 뛰어납니다. –

+0

아마도이 코드를 C# 코드로 편집 할 수 있습니까? –

5

(참조 :

나는 종종 문제를 해결하기 위해 두 개의 목록 방식을 사용 삭제 된 자신의 RowState 속성을 변경할 수 있지만 테이블에서 삭제 된 행을 떠나 행에 삭제 호출

DataTable dt; 
// remove all rows where the last name starts with "B" 
foreach (DataRow row in dt.Rows) 
{ 
    if (row["LASTNAME"].ToString().StartsWith("B")) 
    { 
     // mark the row for deletion: 
     row.Delete(); 
    } 
} 

: 코멘트), 여기 당신이 행을 삭제하는 방법의 예입니다. 테이블의 내용에서 삭제 된 행을 뺀 값을 표시하려는 경우와 같이 변경 사항을 서버에 다시 적용하기 전에이 테이블을 사용하여 작업해야하는 경우 다음과 같이 반복하면서 각 행의 RowState를 확인해야합니다 : 컬렉션에서 (브루노의 대답 등)

foreach (DataRow row in dt.Rows) 
{ 
    if (row.RowState != DataRowState.Deleted) 
    { 
     // this row has not been deleted - go ahead and show it 
    } 
} 

제거 행은 테이블 어댑터를 깰 것이며, 일반적으로 DataTable을 함께 수행 할 수 없습니다.

87

List를 거꾸로 반복하는 것이 더 나은 접근 방법처럼 들립니다. 왜냐하면 만약 당신이 다른 요소들을 "틈에 빠지다"면, 당신은 이미 그것들을 보았 기 때문에 상관 없습니다. 또한 카운터 변수가 .Count보다 커질 염려가 없습니다.

 List<int> test = new List<int>(); 
     test.Add(1); 
     test.Add(2); 
     test.Add(3); 
     test.Add(4); 
     test.Add(5); 
     test.Add(6); 
     test.Add(7); 
     test.Add(8); 
     for (int i = test.Count-1; i > -1; i--) 
     { 
      if(someCondition){ 
       test.RemoveAt(i); 
      } 
     } 
0

내가 열거하고있는 컬렉션에서 항목을 제거해야 할 때 나는 보통 그것을 역순으로 나열합니다.

33

@bruno 코드를 사용하면 거꾸로 할 수 있습니다.

뒤로 이동하면 누락 된 배열 인덱스가 루프 순서를 간섭하지 않기 때문에.

var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 }); 

for (int i = l.Count - 1; i >= 0; i--) 
    if (l[i] % 2 == 0) 
     l.RemoveAt(i); 

foreach (var i in l) 
{ 
    Console.WriteLine(i); 
} 

그러나 seriuosly, 요즘, 내가 LINQ를 사용하십시오 : 당신이 .NET 2를 표적으로하는 경우

var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 }); 

l.RemoveAll(n => n % 2 == 0); 
+8

+1 이런 식으로 LINQ의 힘을 실현했습니다. – BenAlabaster

+0

할 필요가 없을 때 왜 먼 길을할까요? 목록 l을 목록 대신 으로 정의하는 것이 왜 var 대신에 정의 될까요? 이 될 것입니다. +1하지만 RemoveAll의 경우 – sebagomez

+6

+1입니다. 참고 RemoveAll은 LINQ가 아닙니다. LINQ 지원없이 .NET 2.0의 모든 'List'클래스에서 사용할 수 있습니다. –

3

chakrit의 솔루션도 사용할 수 있습니다.0 (LINQ/lambda 식 없음)을 람다식이 아닌 대리자를 사용하여 계산합니다.

public bool IsMatch(int item) { 
    return (item % 3 == 1); // put whatever condition you want here 
} 
public void RemoveMatching() { 
    List<int> x = new List<int>(); 
    x.RemoveAll(new Predicate<int>(IsMatch)); 
}