2009-10-10 36 views
56

Khác với bước qua các yếu tố từng người một, làm thế nào để tôi so sánh hai danh sách các chuỗi đẳng thức (trong .NET 3.0):So sánh hai Danh sách <string> cho bình đẳng

này thất bại:

// 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

thể trùng lặp của [Thế nào là cách tốt nhất để kiểm tra hai Danh sách danh sách cho sự bình đẳng trong C#] (http://stackoverflow.com/questions/876508/what-is-the-best-way-to-check-hai-listt-danh sách-cho-bình đẳng-in-c-sắc nét) – nawfal

Trả lời

40

Nhiều khuôn khổ thử nghiệm cung cấp một lớp CollectionAssert:

CollectionAssert.AreEqual(expected, actual); 

Ví dụ MS Test

+0

Đồng thời các tin nhắn được cung cấp khi nó không thành công, ví dụ như. "Số lượng phần tử khác nhau" hoặc "Phần tử ở chỉ mục 0 không khớp", không cho bạn biết * chúng là gì *. –

73

hãy thử như sau

var equal = expected.SequenceEqual(actual); 

phiên bản thử nghiệm

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

Phương pháp mở rộng SequenceEqual sẽ so sánh các phần tử của tập hợp để bình đẳng.

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

+0

Thansk cho câu trả lời của bạn. Đó có phải là .NET 3.5 không? Tôi quên đề cập đến tôi đang sử dụng .NET 3.0. –

+0

@Adam, vâng. SequenceEquals là một phương thức mở rộng được định nghĩa trong 3.5 mặc dù nó khá dễ dàng để chuyển sang dự án 2.0. – JaredPar

+0

Nó sẽ không cung cấp cho bạn thông tin chi tiết về lý do tại sao các bộ sưu tập khác nhau trong khi CollectionAssert.AreEqual() sẽ. –

12

Bạn luôn có thể viết các chức năng cần thiết tự:

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; 
} 

và sử dụng nó :

// 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

Đẹp! Tôi đang tìm cách tránh bước qua các tầng lớp, nhưng đó là một cách chung chung tuyệt vời mà bạn đã viết phương pháp. –

+0

Được bình chọn, đây là câu trả lời hay. Tuy nhiên, lưu ý rằng hàm sẽ ném một ngoại lệ nếu một trong hai danh sách là null. Đề nghị thêm các câu lệnh sau vào đầu hàm: 'if (list1 == null && list2 == null) trả về true;' và 'if (list1 == null || list2 == null) trả về false;' –

10

Tôi nhận thấy không ai thực sự nói với bạn tại sao mã ban đầu của bạn không hoạt động. Điều này là do toán tử == trong các thử nghiệm chung reference equality (tức là nếu hai trường hợp đang trỏ đến cùng một đối tượng trong bộ nhớ) trừ khi toán tử là overloaded. List<T> không xác định toán tử == để tham chiếu cơ sở bằng thực thi được sử dụng.

Khi các áp phích khác đã chứng minh, bạn thường sẽ phải trải qua các yếu tố để kiểm tra "bình đẳng thu". Tất nhiên, bạn nên sử dụng tối ưu hóa được đề xuất bởi người dùng DreamWalker mà trước tiên kiểm tra Tổng số bộ sưu tập trước khi bước qua chúng.

+0

Cảm ơn bạn! Tôi có thể nghĩ ra một số cách để so sánh bản thân mình, nhưng khi tôi gặp phải vấn đề này, tôi nghĩ "À, rõ ràng là không kiểm tra sự bình đẳng, vậy nó đang làm gì?" – JHixson

1

Bạn có thể viết một phương pháp mở rộng như vậy:

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; 
     } 
    } 

Và gọi nó như vậy:

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); 

EDIT: Cập nhật mã để sử dụng một phương pháp tĩnh thay vì kể từ khi OP đang sử dụng .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; 
     } 

Chủ đầu tư:

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

Có được phép trong .NET 3.0 không? –

+0

@Adam: Tôi nhận ra rằng bạn đang sử dụng .NET 3.0 và không .NET 3.5 Tôi sẽ chỉnh sửa câu trả lời của mình để làm cho mã có thể sử dụng được cho .NET 3.0 bằng cách biến nó thành phương pháp tĩnh thay vì phương pháp mở rộng –

0

Trong khi nó lặp qua bộ sưu tập, phương pháp mở rộng mà tôi tạo không yêu cầu thứ tự của hai danh sách giống nhau, và nó cũng hoạt động với các loại phức tạp, miễn là phương thức Equals bị ghi đè.

Hai danh sách sau đây sẽ trở thành sự thật:

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

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

Phương pháp:

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

Sử dụng LINQ và viết code như một phương pháp khuyến nông:

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

Nếu các vấn đề trật tự :

bool equal = a.SequenceEquals(b); 

Nếu thứ tự không quan trọng:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b); 
Các vấn đề liên quan