2010-03-23 18 views
18

मैं तार की दो सूचियां पर एक कस्टम comparer को लागू करने और .Except() LINQ विधि का उपयोग उन है कि सूचियों में से एक एक नहीं हैं पाने के लिए कोशिश कर रहा हूँ। कारण मैं एक कस्टम तुलनात्मक कर रहा हूं क्योंकि मुझे "अस्पष्ट" तुलना करने की आवश्यकता है, यानी एक सूची में एक स्ट्रिंग को दूसरी सूची में एक स्ट्रिंग के अंदर एम्बेड किया जा सकता है।LINQ सिवाय और कस्टम IEqualityComparer

मैं निम्नलिखित comparer

public class ItemFuzzyMatchComparer : IEqualityComparer<string> 
{ 
    bool IEqualityComparer<string>.Equals(string x, string y) 
    { 
     return (x.Contains(y) || y.Contains(x)); 
    } 

    int IEqualityComparer<string>.GetHashCode(string obj) 
    { 
     if (Object.ReferenceEquals(obj, null)) 
      return 0; 
     return obj.GetHashCode(); 
    } 
} 

जब मैं डिबग, केवल ब्रेकप्वाइंट कि हिट विधि GetHashCode() में है बनाया है। बराबर() कभी छुआ नहीं जाता है। कोई विचार?

+0

मेरे लिए यह एक अच्छा अभ्यास था। मेरे मामले में मैं 'सार्वजनिक int GetHashCode (स्ट्रिंग obj) {वापसी obj.ToLower()। GetHashCode();}' आपका प्रश्न पुराना है लेकिन मैं 4 साल बाद एक ही मुद्दे में भाग गया। –

उत्तर

18

सभी हैश लौटे कोड भिन्न हैं, तो यह कभी नहीं समानता के लिए तुलना करने के लिए की जरूरत है।

असल में समस्या यह है कि आपकी हैश और समानता अवधारणाएं बहुत अलग हैं। मुझे पूरा यकीन नहीं है कि आप इसे कैसे सही करेंगे, लेकिन जब तक आप ऐसा नहीं कर लेते हैं तो यह निश्चित रूप से काम नहीं करेगा।

तुम्हें यकीन है कि अगर Equals(a, b) रिटर्न सच है, तो GetHashCode(a) == GetHashCode(b) बनाने की जरूरत है। (रिवर्स को सच नहीं होना चाहिए - हैश टकराव स्वीकार्य है, हालांकि जाहिर है कि आप उनमें से कुछ को यथासंभव चाहते हैं।)

+0

मुझे लगता है कि यह पूर्वनिर्धारित वस्तुओं (यानी तार) के संग्रह पर एक कस्टम तुलना लागू करने का प्रयास करने का एक मामला है। अगर मुझे कस्टम ऑब्जेक्ट्स का संग्रह करना पड़े, तो शायद मैं इसे काम पर ला सकता हूं। मुझे लगता है कि मुझे उससे बेहतर तरीके से आना होगा। :(मैं इसे किसी दिन के लिए अनुत्तरित के रूप में छोड़ दूंगा ताकि किसी और के पास कोई सुझाव हो। – Joe

+0

मैंने इसे दो चरणों में कर दिया। मैंने उन वस्तुओं की एक सूची जेनरेट की जो आंशिक रूप से किसी एक का उपयोग करके मेल खाते थे, फिर घूमते थे और करते थे पहली सूची के खिलाफ उस सबसेट का उपयोग करने के अलावा। आपकी मदद के लिए धन्यवाद। – Joe

5

जैसा कि जॉन ने बताया, आपको यह सुनिश्चित करना होगा कि हैश कोड दो तार जो बराबर हैं (आपके तुलना नियम के अनुसार)। यह दुर्भाग्य से काफी मुश्किल है।

समस्या, Equals(str, "") रिटर्न सभी स्ट्रिंग्स str है, जो अनिवार्य रूप से मतलब है कि सभी तार एक रिक्त स्ट्रिंग पर है और इसके परिणामस्वरूप बराबर हैं के लिए सच का प्रदर्शन करने के लिए, सभी स्ट्रिंग्स कोई रिक्त स्ट्रिंग के रूप में ही हैश कोड होना चाहिए।

public class ItemFuzzyMatchComparer : IEqualityComparer<string> { 
    bool IEqualityComparer<string>.Equals(string x, string y) { 
    return (x.Contains(y) || y.Contains(x)); 
    } 
    int IEqualityComparer<string>.GetHashCode(string obj) { 
    if (Object.ReferenceEquals(obj, null)) return 0; 
    return 1; 
    } 
} 

तो फिर तुम Except विधि का उपयोग कर सकते हैं और इसे सही ढंग से व्यवहार करेंगे: इसलिए, IEqualityComparer सही ढंग से लागू करने के लिए एक ही रास्ता हमेशा एक ही हैश कोड वापस जाने के लिए है। एकमात्र समस्या यह है कि आप (शायद) एक सुंदर अक्षम कार्यान्वयन प्राप्त करेंगे, इसलिए यदि आपको बेहतर प्रदर्शन की आवश्यकता है, तो आपको अपना खुद का Except लागू करना पड़ सकता है। हालांकि, मुझे बिल्कुल यकीन नहीं है कि LINQ कार्यान्वयन कितना अक्षम होगा और मुझे यकीन नहीं है कि वास्तव में आपके तुलना नियम के लिए कोई प्रभावी कार्यान्वयन संभव है या नहीं।

1

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

List<String> listOne = new List<string>(){"hard", "fun", "code", "rocks"}; 
List<String> listTwo = new List<string>(){"fund", "ode", "ard"}; 

var fuzzyMatchList = from str in listOne 
         from sr2 in listTwo 
         where str.Contains(sr2) || sr2.Contains(str) 
         select str; 
var exceptList = listOne.Except(fuzzyMatchList); 
संबंधित मुद्दे