2012-02-24 11 views
11

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

उदाहरण के लिए ::

d.Add(1, "1"); 
d.Add(2, "1"); // This would not be OK because "1" has already been used as a value. 

मैं जानता हूँ कि यह विदेशी की तरह है, लेकिन ऐसा लगता है कि यह मौजूद हो सकता है के बाद से देखते हैं बीसीएल में संग्रह प्रकार अरब एक के बारे में। कोई विचार?

+3

कुंजी का मूल्य भाग बनाएं। –

+3

.NET Framework में ऐसी कोई कक्षा नहीं है। लेकिन आप आसानी से एक शब्दकोश और एक हैशसेट, या दो शब्दकोशों में से एक बना सकते हैं। – dtb

+1

@ रॉबर्ट हार्वे: अगर वह ऐसा करता है तो वह अब 'डी [1]' नहीं कर सकता, जो शब्दकोश के उद्देश्य को हरा देता है। होशसेट का भी उपयोग कर सकते हैं <> –

उत्तर

13

शब्दकोश और हैशसेट/माध्यमिक रिवर्स डिक्शनरी के बारे में कैसे - यह समस्या को हल करेगा और एकल शब्दकोश पर चेक से बेहतर प्रदर्शन करेगा।

कुछ इस तरह, वर्ग के रूप में लिपटे:

HashSet<string> secondary = new HashSet<string>(/*StringComparer.InvariantCultureIgnoreCase*/); 
Dictionary<int, string>dictionary = new Dictionary<int, string>(); 
object syncer = new object(); 

public override void Add(int key, string value) 
{ 
    lock(syncer) 
    { 
    if(dictionary.ContainsKey(key)) 
    { 
     throw new Exception("Key already exists"); 
    } 

    if(secondary.Add(value) 
    { 
     throw new Exception("Value already exists"); 
    } 
    dictionary.Add(key, value); 
    } 
} 
+1

के लिए वेब पर खोजें और फिर इसे कस्टम क्लास में लपेटें। – Jason

+0

@ जेसन यदि आपको इसकी आवश्यकता है 1 बार से - निश्चित रूप से हाँ! –

+1

@OlegDok यदि आपको 1 से अधिक समय कोड पढ़ना है - निश्चित रूप से हाँ! (और आपको हमेशा इस कोड को कुछ दिन फिर से पढ़ना होगा।) –

0

here इस तरह की एक प्रकार है कि स्थित एक परियोजना है। इसे PairDictionary कहा जाता है और यह बहुत अच्छी तरह से काम करता है। सबसे अच्छा जवाब नहीं है, लेकिन किसी भी व्यक्ति के लिए जो उस कस्टम वर्ग की जरूरत है।

+0

'PairDictionary 'एक भयानक समाधान है। आंतरिक रूप से यह सूचियों के साथ काम करता है और प्रत्येक ऑपरेशन _ (_) _real_ शब्दकोश --- [स्रोत] के ओ (1) के विपरीत एक ओ (एन) ऑपरेशन है (http://curations.codeplex.com/SourceControl/ नवीनतम # Curations/PairDictionary.cs) – t3chb0t

+0

@ t3chb0t आप कार्यान्वयन पर ध्यान केंद्रित कर रहे हैं और एपीआई नहीं। हाँ, यह सबसे अच्छा नहीं है, लेकिन इसका उपयोग महत्वपूर्ण है। एस इन्स जो कुछ ओपन सोर्स कोड का हिस्सा है, आपको एक पैच सबमिट करना चाहिए जो कार्यक्षमता में सुधार करता है :) –

0

मैंने डेटा को Dictionary<TKey, HashSet<TValue>> के रूप में संग्रहीत करके इस समस्या को हल किया। यदि आप एक मूल्य चाहते हैं जिसमें 2 प्राथमिक कुंजी हैं तो आप हैशसेट को किसी अन्य शब्दकोश से प्रतिस्थापित कर सकते हैं।

Dictionary<int, HashSet<int>> _myUniquePairOfIntegerKeys; 
// OR 
Dictionary<string, Dictionary<string, bool>> _myUniquePairOfStringKeysWithABooleanValue; 
1

आंतरिक puposes के लिए मैंने BiDictionary लिखा था। यह बुलेट प्रूफ नहीं है क्योंकि मैं इसे उपयोगकर्ता को बेनकाब नहीं करता हूं, इसलिए यह मेरे लिए ठीक काम करता है। यह मुझे या तो कुंजी प्राप्त करने की अनुमति देता है क्योंकि मुझे आवश्यकता है।

KeyPair<,>IEnumerable<,> को लागू करने में सक्षम होना आवश्यक है और इस प्रकार Add विधि ताकि हम ऑब्जेक्ट प्रारंभकर्ता का उपयोग कर सकें।

internal class KeyPair<TKey1, TKey2> 
{ 
    public TKey1 Key1 { get; set; } 
    public TKey2 Key2 { get; set; } 
} 

यह एक गतिशील वस्तु के रूप में मुख्य वर्ग इतना है कि हम इस पर प्रमुख के नाम का इस्तेमाल कर सकते हैं जब मूल्यों को पुन: प्राप्त है:

internal class BiDictionary<TKey1, TKey2> : DynamicObject, IEnumerable<KeyPair<TKey1, TKey2>> 
{ 
    private readonly Dictionary<TKey1, TKey2> _K1K2 = new Dictionary<TKey1, TKey2>(); 
    private readonly Dictionary<TKey2, TKey1> _K2K1 = new Dictionary<TKey2, TKey1>(); 

    private readonly string _key1Name; 
    private readonly string _key2Name; 

    public BiDictionary(string key1Name, string key2Name) 
    { 
     _key1Name = key1Name; 
     _key2Name = key2Name; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (binder.Name == _key1Name) 
     { 
      result = _K1K2; 
      return true; 
     } 

     if (binder.Name == _key2Name) 
     { 
      result = _K2K1; 
      return true; 
     } 

     result = null; 
     return false; 
    } 

    public void Add(TKey1 key1, TKey2 key2) 
    { 
     _K1K2.Add(key1, key2); 
     _K2K1.Add(key2, key1); 
    } 

    public IEnumerator<KeyPair<TKey1, TKey2>> GetEnumerator() 
    { 
     return _K1K2.Zip(_K2K1, (d1, d2) => new KeyPair<TKey1, TKey2> 
     { 
      Key1 = d1.Key, 
      Key2 = d2.Key 
     }).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

उदाहरण:

dynamic bidic = new BiDictionary<string, string>("Key1", "Key2") 
{ 
    { "foo", "bar" }, 
    { "baz", "qux" } 
}; 
var bar = bidic.Key1["foo"]; 
var foo = bidic.Key2["bar"]; 

वे हो सकता है यदि आप बाहर के किसी भी शब्दकोश को संशोधित करते हैं तो सिंक से बाहर निकलें। इस उद्देश्य के लिए मैं ObservableDictionary का उपयोग करता हूं ताकि अगर कोई बदलता है लेकिन सादगी के लिए मैं दूसरे को अपडेट कर सकता हूं तो मैंने मुख्य तर्क को केवल डेमोस्टेट करने के लिए कोड के इस भाग को हटा दिया।

संबंधित मुद्दे