2013-02-27 1 views
1

나는 왜 for 루프가 한 번만 반복되는지 전혀 모른다. 나는 논리가 맞다고 생각한다. 아래는 코드이다.C# 왜 List.Remove()가 'for loop'을 나눕니까?

// the list is named 'dataList' 

for(int i = 0 ; i < dataList.Count; i ++) 
{ 
    string[] data = dataList[i].Split('+'); 
    string[] wsno = data[0].Split(':'); 
    if(wsno[1].Equals(tbWorkSheet.Text)) 
    { 
     dataList.Remove(dataList[i]) <<<< remove string that has the same number 
     //data removed 
     //for loop ends up here idk why.. 
    } 
} 

dataList.Count는 목록의 크기가됩니다.

이 경우는 .. 목록에 저장된 여러 문자열을 제거하려면 각 문자열에 그룹 번호가 있습니다. 그래서 for 루프는 마지막 루프까지 반복됩니다. 그러나 원하는 번호와 동일한 번호의 문자열을 발견하면이를 제거 할 if 문을 실행합니다.

+0

'dataList.Count'가 어떤 값을 구체적으로 무엇입니까? – Arran

+0

반복 횟수는 얼마나됩니까? 그것은 예외를 던지고 있습니까? –

+0

일반적으로이 작업을 역순으로 수행하면 (즉, count-1에서 0으로) 인덱스 관리를 훨씬 쉽게 할 수 있습니다. – spender

답변

6

이것은 매우 나쁜 생각입니다. 목록에서 값을 제거하면 목록의 다음 항목으로 건너 뜁니다.

예를 들어

당신은 인덱스 0, 1에서 목록에서 3 개 항목이, 2

첫 번째 반복 : 나는 = 0 이제 인덱스 0 항목이 인덱스 0 목록 항목을 제거, 1 (주먹 제거 된 항목).

두 번째 반복 : i = 1 인덱스 1에있는 항목을 0으로 이동하는 방법은 다음과 같습니다. 인덱스 카운터가 0에서 1로 이동하는 동안이 항목을 "건너 뜁니다".

목록에 2 개의 항목 만있는 경우 처음 제거한 후에 휴식을 취할 것입니다. 이것은 색인이 증가하는 동안 카운트가 감소하기 때문입니다.

역순으로이 문제를 제거합니다.

List<int> list = new List<int> { 2, 1 }; 
for (int i = list.Count - 1; i >= 0; i--) 
{ 
    list.RemoveAt(i); 
} 

편집 : Rawling 당신이 항목을 제거 할 때 당신이 당신의 카운터을 감소 경우 앞으로 갈 수 있습니다 언급한다. 루프 뒤로 목록을

for (int i = 0; i < list.Count; i++) 
{ 
    list.RemoveAt(i--); 
} 
+1

이것은 표준적인 방법입니다. –

+0

나는 뭔가를 제거 할 때 전진하고 감소시키는 'i'를 고려할 것이지만, 아마도 전방을 통과하는 것이 중요 할 때만 가능할 것입니다. – Rawling

+0

와우 감사합니다. 이 작품 .. –

-5

for 루프에서 목록을 변경할 수 없습니다. 제거 할 데이터를 다른 목록에 유지 한 다음 루프를 종료 한 후 제거 할 수 있습니다.

+1

하실 수 있습니다. foreach 루프를 사용할 수 없습니다. – Corak

0

항목을 제거한 후 i을 (를) 감소시키는 것을 잊어 버렸습니다. 모든 항목의 번호가 1 씩 변경되므로 다음 항목을 건너 뜁니다.

0

:

for(int i = dataList.Count; i >= 0 ; i--) 
{ 
    string[] data = dataList[i].Split('+'); 
    string[] wsno = data[0].Split(':'); 
    if(wsno[1].Equals(tbWorkSheet.Text)) 
    { 
     dataList.RemoveAt(dataList[i]) <<<< remove string that has the same number 
     //data removed 
     //for loop ends up here idk why.. 
    } 
} 
+1

목록에 중복 된 항목이있는 경우에도 문제가 발생할 수 있습니다. '제거'는 'i'번째 요소를 제거하지 못할 수도 있습니다. 'RemoveAt'가 더 좋을 것입니다. – Rawling

3

당신은 List.RemoveAll 일반적인 방법을 사용할 수 있습니다. 메서드는 술어와 일치하는 모든 항목을 List에서 제거합니다. 방법 서명은 다음입니다 :

INT의 List.RemoveAll (술어의 일치)

그것은 제거 된 요소의 수를 반환합니다.

참조 MSDN은 : http://msdn.microsoft.com/en-US/library/wdka673a(v=vs.110).aspx

0

나는 새로운 목록을 만들기보다는 원래의 콜렉션을 수정 원합니다.

는 LINQ와 함께 깔끔하게 수행 할 수 있습니다

dataList = 
    dataList 
     .Select(x => new{ 
      dataItem = x, 
      secondWsno = x.Split('+').First().Split(':').Skip(1).First() 
     }) 
     .Where(x => !x.secondWsno.Equals(tbWorkSheet.Text)) 
     .ToList(); 
+0

많은 항목이있는 목록이 있고 하나 또는 두 개만 제거하는 경우 목록의 일부만 삭제하면됩니다. 상당한 비율을 제거 할 때 일반적으로 더 좋습니다. – Servy

+0

이러한 작업의 비용을 과대 평가하는 것은 쉽습니다. 문제가되는 것을보기 전까지는 이렇게하는 것이 좋겠지 만, 사소한 제거의 경우에는 잔인 할 수도 있습니다. – spender

관련 문제