2009-10-10 3 views
56

내가 (.NET 3.0) 평등에 대한 문자열의 두 목록을 비교 어떻게, 하나의 요소 하나를 단계별로보다 기타 :평등을위한 두 개의 목록 <string> 비교

이 실패

// Expected result. 
List<string> expected = new List<string>(); 
expected.Add("a"); 
expected.Add("b"); 
expected.Add("c"); 

// Actual result 
actual = new List<string>(); 
actual.Add("a"); 
actual.Add("b"); 
actual.Add("c"); 

// Verdict 
Assert.IsTrue(actual == expected); 
+0

가능한 중복 [어떤 두 개의 목록을 C#에서 평등 목록을 확인하는 가장 좋은 방법은 (http://stackoverflow.com/questions/876508/what-is-the-the-the-the-way-to-check-two-listt-lists-c-sharp의 동등 함) – nawfal

답변

40

많은 테스트 프레임 워크는 CollectionAssert 클래스를 제공 참조 :

CollectionAssert.AreEqual(expected, actual); 

예를 MS Test

+0

실패 할 때 제공되는 메시지는 약간 유용하지 않습니다. "다른 수의 요소"또는 "인덱스 0의 요소가 일치하지 않습니다.", 당신이 * 무엇인지 알리지 않고 *. –

73

다음

var equal = expected.SequenceEqual(actual); 

테스트 버전

Assert.IsTrue(actual.SequenceEqual(expected)); 
시도

SequenceEqual 확장 메서드는 컬렉션의 요소를 비교하여 동일한 지 확인합니다.

http://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx

+0

당신의 답을위한 Thansk. NET 3.5인가요? .NET 3.0을 사용하고 있음을 언급하는 것을 잊었습니다. –

+0

@ Adam, 예. SequenceEquals는 2.0 프로젝트로 이식하는 것이 쉽지만 3.5에서 정의 된 확장 메소드입니다. – JaredPar

+0

CollectionAssert.AreEqual()을 사용하는 반면 컬렉션이 다른 이유에 대한 세부 정보는 제공하지 않습니다. –

12

당신은 항상 필요한 기능을 직접 작성할 수 있습니다

public static bool ListEquals<T>(IList<T> list1, IList<T> list2) { 
    if (list1.Count != list2.Count) 
     return false; 
    for (int i = 0; i < list1.Count; i++) 
     if (!list1[i].Equals(list2[i])) 
      return false; 
    return true; 
} 

및 사용 :

// Expected result. 
List<string> expected = new List<string>(); 
expected.Add("a"); 
expected.Add("b"); 
expected.Add("c"); 

// Actual result 
actual = new List<string>(); 
actual.Add("a"); 
actual.Add("b"); 
actual.Add("c"); 

// Verdict 
Assert.IsTrue(ListEquals(actual, expected)); 
+0

니스! elments를 통해 단계별로 진행되는 것을 피하기 위해 찾고 있었지만 방법을 작성한 훌륭한 일반적인 방법입니다. –

+0

Upvoted, 이것은 좋은 대답입니다. 그러나 두 목록 중 하나가 null이면 함수가 예외를 throw합니다. 함수 시작 부분에 다음 명령문을 추가하는 것이 좋습니다 :'if (list1 == null && list2 == null) true를 반환하고'(list1 == null || list2 == null) false를 반환하면, –

10

원래 코드가 작동하지 않는 이유는 아무도 알려지지 않았습니다. 이는 == 연산자가 일반적으로 연산자가 overloaded이 아닌 한 reference equality (즉, 두 인스턴스가 메모리의 같은 객체를 가리키는 경우)을 테스트하기 때문입니다. List<T>== 연산자를 정의하지 않으므로 기본 참조 같음 구현이 사용됩니다.

다른 포스터에서 설명한 것처럼 일반적으로 "컬렉션 평등성"을 테스트하기 위해 요소를 단계별로 따라야합니다. 물론, 사용자 DreamWalker이 제안한 최적화를 사용하여 먼저 수집 횟수를 테스트 한 후이를 수행해야합니다.

public static class ListExtensions 
    { 
     public static bool IsEqual<T>(this IList<T> list,IList<T> target, IComparer<T> comparer) where T:IComparable<T> 
     { 
      if (list.Count != target.Count) 
      { 
       return false; 
      } 
      int index = 0; 
      while (index < list.Count && 
        comparer.Compare(list[index],target[index]) == 0) 
      { 
       index++; 
      } 
      if (index != list.Count) 
      { 
       return false; 
      } 
      return true; 
     } 
    } 

을 그래서 같이 호출 :

+0

당신! 나는 그 자신을 비교하는 몇 가지 방법을 생각할 수 있었지만,이 문제에 부딪쳤을 때, 나는 "글쎄, 분명히 평등을 검사하지 않고있다. 그래서 그것은 무엇을하고 있는가?"라고 생각했다. – JHixson

1

당신과 같이 확장 방법을 쓸 수

List<int> intList = new List<int> { 1, 234, 2, 324, 324, 2 }; 
List<int> targetList = new List<int> { 1, 234, 2, 324, 324 }; 
bool isEqual = intList.IsEqual(targetList, Comparer<int>.Default); 

편집 : OP는 .NET을 사용하는 대신에 있기 때문에 정적 인 방법을 사용하는 코드 업데이트 3.0

public static bool IsEqual<T>(IList<T> sourceList, IList<T> targetList, IComparer<T> comparer) where T : IComparable<T> 
     { 
      if (sourceList.Count != targetList.Count) 
      { 
       return false; 
      } 
      int index = 0; 
      while (index < sourceList.Count && 
        comparer.Compare(sourceList[index], targetList[index]) == 0) 
      { 
       index++; 
      } 
      if (index != sourceList.Count) 
      { 
       return false; 
      } 
      return true; 
     } 

클라이언트 :

 bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default); 
+0

.NET 3.0에서 허용됩니까? –

+0

@Adam : .NET 3.0이 아니라 .NET 3.5를 사용하고 있다는 것을 깨달았습니다. 내 대답을 편집하여 .NET 3.0에서 코드를 확장 메서드 대신 정적 메서드로 만들 수있게했습니다. –

0

내가 만든이 확장 메서드는 두 목록의 순서가 동일 할 필요가 없으며 Equals 메서드가 재정의되어있는 한 복잡한 형식에서도 작동합니다.

다음 두 목록은 사실 반환 :

List<string> list1 = new List<string> 
{ 
    { "bob" }, 
    { "sally" }, 
    { "john" } 
}; 

List<string> list2 = new List<string> 
{ 
    { "sally" }, 
    { "john" }, 
    { "bob" } 
}; 

방법 :

public static bool IsEqualTo<T>(this IList<T> list1, IList<T> list2) 
{ 
    if (list1.Count != list2.Count) 
    { 
     return false; 
    } 

    List<T> list3 = new List<T>(); 

    foreach (var item in list2) 
    { 
     list3.Add(item); 
    } 

    foreach (var item in list1) 
    { 
     int index = -1; 
     for (int x = 0; x < list3.Count; x++) 
     { 
      if (list3[x].Equals(item)) 
      { 
       index = x; 
      } 
     } 

     if (index > -1) 
     { 
      list3.RemoveAt(index); 
     } 
     else 
     { 
      return false; 
     } 
    } 

    return !list3.Any(); 
} 
1

는 Linq를 사용하고 확장 방법으로 코드를 작성 :

public static bool EqualsOtherList<T>(this List<T> thisList, List<T> theOtherList) 
{ 
    if (thisList == null || theOtherList == null || 
     thisList.Count != theOtherList.Count) return false; 
    return !thisList.Where((t, i) => !t.Equals(theOtherList[i])).Any(); 
} 
5

주문 사항의 경우 :

는 순서는 중요하지 않는 경우

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);