2009-03-25 8 views
45

चलो कहते हैं कि मैं इन दो सरणियों करते हैं:सी # में दो सरणी के बीच "diff" प्राप्त करना?

var array1 = new[] {"A", "B", "C"}; 
var array2 = new[] {"A", "C", "D"}; 

मैं दोनों के बीच अंतर प्राप्त करना चाहते हैं। मुझे पता है कि मैं इसे कोड की कुछ पंक्तियों में लिख सकता हूं, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि मुझे अंतर्निहित भाषा सुविधा या LINQ एक्सटेंशन विधि नहीं मिल रही है।

आदर्श रूप में, मैं निम्नलिखित तीन परिणामों के साथ खत्म हो जाएगा:

  • आइटम नहीं array1 में है, लेकिन array2 ('डी')
  • आइटम नहीं array2 में, में हैं, लेकिन array1 में हैं (" बी ")
  • आइटम है कि पहले से दोनों में

धन्यवाद कर रहे हैं!

उत्तर

86

यदि आपके पास LINQ उपलब्ध है, तो आप Except और Distinct का उपयोग कर सकते हैं। सेट हैं कि विवादित लिए कहा प्राधिकरण हैं:

- array2.Except(array1) 
- array1.Except(array2) 
- array1.Intersect(array2) 
+0

क्या आप जानते हैं कि किस प्रकार की प्रदर्शन गारंटीएं हैं?संभावित रूप से छोड़कर पहले प्रत्येक सरणी की एक क्रमबद्ध प्रतिलिपि बनाना होगा। मुझे एमएसडीएन पर इनमें से कोई भी नहीं मिला। – Eclipse

+1

नहीं, यह एक क्रमबद्ध प्रतिलिपि नहीं बनाता है। यह बहिष्कृत अनुक्रम से एक सेट बनाता है, और फिर स्रोत अनुक्रम पर पुनरावृत्त करता है, जो किसी भी तत्व को उपरोक्त अनुक्रम में नहीं देता है। –

+3

(जब मैं कहता हूं "सेट" मेरा मतलब है "हैश सेट"।) –

10
MSDN 101 LINQ samples से

....

public void Linq52() { 
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; 
    int[] numbersB = { 1, 3, 5, 7, 8 }; 

    IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB); 

    Console.WriteLine("Numbers in first array but not second array:"); 
    foreach (var n in aOnlyNumbers) { 
     Console.WriteLine(n); 
    } 
} 
3

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

int iA = 0; 
int iB = 0; 
List<int> inA = new List<int>(); 
List<int> inB = new List<int>(); 
List<int> inBoth = new List<int>(); 
while (iA < numbersA.Length && iB < numbersB.Length) 
{ 
    if (numbersA[iA] < numbersB[iB]) 
    { 
     inA.Add(numbersA[iA++]); 
    } 
    else if (numbersA[iA] == numbersB[iB]) 
    { 
     inBoth.Add(numbersA[iA++]); 
     ++iB; 
    } 
    else 
    { 
     inB.Add(numbersB[iB++]); 
    } 
} 
while (iA < numbersA.Length) 
{ 
    inA.Add(numbersA[iA++]); 
} 
while (iB < numbersB.Length) 
{ 
    inB.Add(numbersB[iB++]); 
} 

फिर, यह वास्तव में केवल तभी जरूरी है जब आप सैकड़ों हजारों मूल्यों से निपट रहे हों।

3

यहां LINQ एक्सटेंशन विधियों के मानक हैं। परिणाम एक वास्तविक कार्यक्रम के विकास के दौरान प्राप्त किए गए थे।

परीक्षण: 2 सूचियां (lst1 और lst2) प्रत्येक लगभग 250000 ऑब्जेक्ट्स। प्रत्येक ऑब्जेक्ट (क्लास कुंजी) में एक स्ट्रिंग और एक पूर्णांक होता है। दूसरी सूची में सबसे पहले एक ही प्रविष्टियां होती हैं, लेकिन कुछ नई प्रविष्टियां जोड़ दी जाती हैं और कुछ हटा दी जाती हैं।

मैंने एक्सेप्शन एक्सटेंशन विधि का परीक्षण किया।

var को छोड़कर = lst2.Except (lst1);

सूची lst = को छोड़कर .सूची();

इन 2 लाइनों ने "नए परिवर्धन" की 600 आइटम सूची बनाई। मैंने स्टॉपवॉच ऑब्जेक्ट का उपयोग करके इसे समय दिया। गति आश्चर्यजनक है: 220 एमएस। मैंने जो कंप्यूटर इस्तेमाल किया वह किसी भी तरह से "तेज़ गोंजालेस" नहीं है। कोर 2 डुओ T7700 - 2.4GHz।

नोट:

यहाँ वर्ग कुंजी है, जो IEquatable मैं चेहरा लागू करता है।

public class Key : IEquatable<Key> 
{ 
    public int Index { get; private set; } 
    public string Name { get; private set; } 

    public Key(string keyName, int sdIndex) 
    { 
     this.Name = keyName; 
     this.Index = sdIndex; 
    } 

// IEquatable implementation 
    public bool Equals(Key other) 
    { 
     //Check whether the compared object is null. 
     if (Object.ReferenceEquals(other, null)) return false; 
     //Check whether the compared object references the same data. 
     if (Object.ReferenceEquals(this, other)) return true; 
     //Check whether the products' properties are equal. 
     return Index.Equals(other.Index) && Name.Equals(other.Name); 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 
    public override int GetHashCode() 
    { 
     //Get hash code for the name field if it is not null. 
     int hashKeyName = Name == null ? 0 : Name.GetHashCode(); 
     //Get hash code for the index field. 
     int hashKeyIndex = Index.GetHashCode(); 
     //Calculate the hash code for the Key. 
     return hashKeyName^hashKeyIndex; 
    } 
} 
संबंधित मुद्दे