2013-05-01 2 views
-2

내 응용 프로그램에서 내 컨트롤에서 벗어난 데이터 소스에서 발생하는 데이터 컬렉션을 처리해야합니다. 이러한 콜렉션 중 일부는 널 (null) 검사 코드를 흩 뿌리기보다는 제 코드를 누르 자마자 걸러내는 것을 선호하는 널 (null)을 포함합니다. 나는 재사용 가능한 일반적인 방식으로이 일을 원하고 그것을이 방법을 쓴 :컬렉션에서 모든 null 제거

collection.RemoveAll(x => x == null); 
:

나는 구체적인 목록 클래스에 알
public static void RemoveNulls<T>(this IList<T> collection) where T : class 
    { 
     for (var i = 0; i < collection.Count(); i++) 
     { 
      if (collection[i] == null) 
       collection.RemoveAt(i); 
     } 
    } 

이처럼 사용할 수있는 RemoveAll() 방법이있다

하지만 많은 반환 유형은 구체적인 유형이 아닌 인터페이스 기반 (IList/IList ...)입니다.

+1

왜 'RemoveAll'을 사용할 수 없는지 자세히 설명해 주시겠습니까? –

+1

그리고 뭐가 문제입니까? –

+2

항목을 제거하면 모든 후속 요소의 색인이 1 씩 아래쪽으로 이동하기 때문에 작성한 코드는 작동하지 않습니다. 널을 제거 할 때마다 코드는 다음 요소 검사를 건너 뜁니다. –

답변

14

대신 소스 컬렉션에서 널 (null)을 제거, 당신은 LINQ를 사용하여 널 (null)없이 수집의 복사본을 만들 수 있습니다

collection.Where(i => i != null).ToList(); 

확장 방법은 IList를 포함하여 모든를 IEnumerable에서 작동합니다.

+0

불필요하게 전체 컬렉션을 복사해야하는 이유는 무엇입니까? – Jammer

+3

@ Jammer, 당신은 또한'.ToList()'부분을 드롭하여 필터로 사용할 수 있습니다. 성능에 신경 쓰면 모든 RemoveAt가 제거 된 항목 뒤에 오는 모든 목록 항목을 이동한다는 점을 명심하십시오. 따라서 목록의 시작 부분에서 1000 개의 항목으로 10 개의 항목을 제거하면 적어도 990 개의 항목이 메모리에서 10 번 이동됩니다. – alex

+1

'IList '(적어도리스트 과 같은 배열 백업을 사용하여) 요소를 제거하면 모든 후속 요소를 사용자가 할 때마다 한 슬롯 아래로 강제로 복사하므로 실제로 성능이 향상 될 수 있습니다. –

4

요소를 제거하면 모든 후속 요소의 색인이 감소하기 때문에 메서드가 작동하지 않습니다. Linq 솔루션을 원하지 않는다면 (@alex의 답을 보면 가장 간단한 것처럼 보입니다.) 역순으로 반복해야합니다.

public static void RemoveNulls<T>(this IList<T> collection) where T : class 
{ 
    for (var i = collection.Count-1; i >= 0 ; i--) 
    { 
     if (collection[i] == null) 
      collection.RemoveAt(i); 
    } 
} 
+0

여기에서 테스트하는 것이 좋습니다. – Jammer

+0

수정, 바로 당신입니다. – Jammer

+0

"여기에서 테스트하는 것이 좋습니다"- 몇 가지 테스트 사례를 시도해보십시오. 특히, 두 개의 연속 null과 그 뒤에 null이 아닌 모음이 있습니다. – Joe

관련 문제