2009-10-10 12 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

संभव डुप्लिकेट [क्या दो सूची सी # में समानता के लिए सूचियों की जांच करने के लिए सबसे अच्छा तरीका है] (http://stackoverflow.com/questions/876508/समान-सर्वोत्तम-तरीके-से-चेक-दो-सूची-सूचियों के लिए-समानता-इन-सी-तेज) – nawfal

उत्तर

40

कई परीक्षण चौखटे एक CollectionAssert वर्ग प्रदान करते हैं:

CollectionAssert.AreEqual(expected, actual); 

जैसे MS Test

+0

क्या यह विफल होने पर संदेश देता है, उदाहरण के लिए थोड़ा बेकार है। "तत्वों की अलग-अलग संख्या" या "सूचकांक पर तत्व 0 मेल नहीं खाता", आपको बताए बिना * वे क्या हैं *। –

73

निम्नलिखित

var equal = expected.SequenceEqual(actual); 

टेस्ट संस्करण

Assert.IsTrue(actual.SequenceEqual(expected)); 
प्रयास करें

अनुक्रमिक एक्वाल एक्सटेंशन विधि समानता के क्रम में संग्रह के तत्वों की तुलना करेगा।

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

+0

आपके उत्तर के लिए Thansk। क्या वह केवल .NET 3.5 है? मैं उल्लेख करना भूल गया कि मैं .NET 3.0 का उपयोग कर रहा हूं। –

+0

@ एडम, हाँ। SequenceEquals 3.5 में परिभाषित एक विस्तार विधि है हालांकि 2.0 प्रोजेक्ट में बंदरगाह के लिए यह काफी आसान है। – 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

उपरोक्त, यह एक अच्छा जवाब है। हालांकि, ध्यान दें कि यदि कोई सूची शून्य है तो फ़ंक्शन अपवाद फेंक देगा। फ़ंक्शन की शुरुआत में निम्न कथन जोड़ने की अनुशंसा करें: 'if (list1 == null && list2 == null) सत्य लौटाएं;' और 'if (list1 == null || list2 == null) झूठी वापसी; ' –

10

मैंने देखा कि वास्तव में कोई भी आपको नहीं बताया कि आपका मूल कोड क्यों काम नहीं करता है। ऐसा इसलिए है क्योंकि == ऑपरेटर सामान्य परीक्षणों में reference equality (यानी यदि दो उदाहरण स्मृति में एक ही वस्तु को इंगित कर रहे हैं) जब तक ऑपरेटर overloaded नहीं होता है। List<T>== ऑपरेटर को परिभाषित नहीं करता है, इसलिए आधार संदर्भ कार्यान्वयन के बराबर उपयोग किया जाता है।

जैसा कि अन्य पोस्टर ने दिखाया है, आपको आम तौर पर "संग्रह समानता" का परीक्षण करने के लिए तत्वों के माध्यम से कदम उठाना होगा। बेशक, आपको उपयोगकर्ता DreamWalker द्वारा सुझाए गए अनुकूलन का उपयोग करना चाहिए जो पहले उनके माध्यम से कदम उठाने से पहले संग्रह की गणना का परीक्षण करता है।

+0

धन्यवाद आप! मैं खुद तुलना करने के कई तरीकों के बारे में सोच सकता था, लेकिन जब मैं इस मुद्दे में भाग गया, मैंने सोचा "ठीक है, यह स्पष्ट रूप से समानता की जांच नहीं कर रहा है, तो यह क्या कर रहा है?" – JHixson

1

तुम इतनी तरह एक विस्तार विधि लिख सकते हैं:

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

और यह इतनी तरह फोन:

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

संपादित करें: एक स्थिर विधि के बजाय के बाद से ओपी नेट उपयोग कर रहा है उपयोग करने के लिए कोड अपडेट किया गया 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

हालांकि यह संग्रह पर पुनरावृत्ति करता है, लेकिन इस एक्सटेंशन विधि को मैंने दो सूचियों के क्रम की आवश्यकता नहीं है, और यह जटिल प्रकारों के साथ भी काम करता है, जब तक कि बराबर विधि ओवरराइड हो।

निम्नलिखित दो सूचियों सच वापसी होगी:

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.SequenceEquals(b); 

क्रम का कोई प्रभाव नहीं होता है:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b); 
की
संबंधित मुद्दे