2013-05-07 4 views
7

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

मुझे पता है कि अगर कुंजी केवल एक स्ट्रिंग थी, तो मैं शब्दकोश को घोषित करते समय स्ट्रिंग कॉम्पैयर.ऑर्डिनल इग्नोरकेस को पैरामीटर के रूप में पास कर सकता था, लेकिन जब यह कुंजी टुपल होती है तो ऐसा लगता है।

क्या टुपल के दूसरे आइटम पर उपयोग करने के लिए स्ट्रिंगकॉम्पियर निर्दिष्ट करने का कोई तरीका है?

धन्यवाद

उत्तर

13

Dictionary निर्माता है, जो आप कुंजी के लिए एक कस्टम comparer निर्दिष्ट कर सकते हैं का प्रयोग करें this overload। आप एक वर्ग को लागू करने वाली

IEqualityComparer<Tuple<string, DateTime>> 

कौन सा ऐसा दिखाई दे सकता बनाने के साथ इस के साथ होगा:

class CustomEqualityComparer : IEqualityComparer<Tuple<string, DateTime>> 
{ 

    public bool Equals(Tuple<string, DateTime> lhs, Tuple<string, DateTime> rhs) 
    { 
     return 
      StringComparer.CurrentCultureIgnoreCase.Equals(lhs.Item1, rhs.Item1) 
     && lhs.Item2 == rhs.Item2; 
    } 


    public int GetHashCode(Tuple<string, DateTime> tuple) 
    { 
     return StringComparer.CurrentCultureIgnoreCase.GetHashCode(tuple.Item1) 
      ^tuple.Item2.GetHashCode(); 
    } 
} 

यहाँ कोई तर्क चेकों रहे हैं, ताकि निर्माण कोड के रूप में इस का इलाज न करें। इसके अलावा, देखभाल की आवश्यकता है ताकि Equals और GetHashCode कार्यान्वयन सभी महत्वपूर्ण स्थिति को संतुष्ट करते हैं जो यदि दो tuples बराबर तुलना करते हैं, तो उनके पास एक ही हैश कोड होना चाहिए। कस्टम टेक्स्ट तुलनाओं से निपटने पर अतिरिक्त सावधानी बरतने पर बग को पेश करना आसान होता है: उदाहरण के लिए, ऊपर ToLower के बजाय ToLowerInvariant का उपयोग करना एक बग होगा (यद्यपि वह कुछ समय तक सतह नहीं हो सकता है)।

+0

बनाने के लिए @Jon के कोड का इस्तेमाल किया हैश कोड आमतौर पर आपके द्वारा उल्लेख की जाने वाली बग से बचने के लिए सबसे अच्छा काम करता है। मैंने एक प्रस्तावित फिक्स के साथ जवाब संपादित किया है; अगर आपको यह पसंद नहीं है तो कृपया पूर्ववत करें। – dtb

+0

@ डीटीबी: निश्चित रूप से पूर्ववत नहीं किया जाएगा क्योंकि यह एक स्थिरता सुधार भी आईएमओ है। धन्यवाद! – Jon

1

के बाद से तुलना की केस-संवेदी होने जा रहे हैं, तो आप toLower/toUpper विधि स्ट्रिंग पक्ष में जब tuples बनाने इस्तेमाल कर सकते हैं, और फिर हमेशा कम या ऊपरी तार आप पुनर्प्राप्त करने के लिए इस्तेमाल tuples में होगा/शब्दकोश में प्रविष्टियों की तुलना करें।

+1

उन्हें ऊपरी या निचले मामले में परिवर्तित करके स्ट्रिंग की तुलना कुछ संस्कृतियों में ठीक से काम नहीं करती है। StringComparer जैसे StringComparer का उपयोग करना बेहतर है। CurrentCultureIgnoreCase – dtb

0

मैं एक Dictionary<Tuple<>> आवरण में इस की जरूरत है, तो मैं समानता के लिए और प्राप्त करने के लिए जाँच करने के लिए एक ही StringComparer का उपयोग करते हुए एक जेनेरिक वर्जन

public class TupleEqualityComparer<T1, T2> : IEqualityComparer<Tuple<T1, T2>> 
{ 
    private IEqualityComparer<T1> comparer1; 
    private IEqualityComparer<T2> comparer2; 

    public TupleEqualityComparer(IEqualityComparer<T1> comparer1, IEqualityComparer<T2> comparer2) 
    { 
     this.comparer1 = comparer1 ?? EqualityComparer<T1>.Default; 
     this.comparer2 = comparer2 ?? EqualityComparer<T2>.Default; 
    } 

    public bool Equals(Tuple<T1, T2> lhs, Tuple<T1, T2> rhs) 
    { 
     return comparer1.Equals(lhs.Item1, rhs.Item1) && comparer2.Equals(lhs.Item2, rhs.Item2); 
    } 

    public int GetHashCode(Tuple<T1, T2> tuple) 
    { 
     return comparer1.GetHashCode(tuple.Item1)^comparer2.GetHashCode(tuple.Item2); 
    } 

} 

public class Dictionary<TKey1, TKey2, TValue> : Dictionary<Tuple<TKey1, TKey2>, TValue>() 
{ 
    public Dictionary() : base() { } 
    public Dictionary(IEqualityComparer<TKey1> comparer1, IEqualityComparer<TKey2> comparer2) : base(new TupleEqualityComparer<TKey1, Tkey2>(comparer1, comparer2) { } 

    public TValue this[TKey1 key1, TKey2 key2] 
    { 
     get { return base[Tuple.Create(key1, key2)]; } 
    } 

    public void Add(TKey1 key1, TKey2 key2, TValue value) 
    { 
     base.Add(Tuple.Create(key1, key2), value); 
    } 

    public bool ContainsKey(TKey1 key1, TKey2 key2) 
    { 
     return base.ContainsKey(Tuple.Create(key1, key2)); 
    } 

    public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value) 
    { 
     return base.TryGetValue(Tuple.Create(key1, key2), out value); 
    } 
} 

प्रयोग

var dict = new Dictionary<string, DateTime, int>(
    StringComparer.OrdinalIgnoreCase, null); 
dict.Add("value1", DateTime.Now, 123); 
Assert.IsTrue(dict.ContainsKey("VALUe1")); 
संबंधित मुद्दे