2015-12-11 12 views
8

कोई संरचना है कि दोनों इन आपरेशनों के अनुमति देता है?अद्वितीय कुंजी-मान-जोड़ी संग्रह

मेरे समस्या:

मैं मूल रूप से कुंजी का मान प्राप्त करने में सक्षम होने की जरूरत है या मूल्य के प्रमुख वास्तव में तेजी से, स्मृति को डुप्लिकेट के बिना (ताकि दो शब्दकोशों सवाल से बाहर हैं)।

बहुत महत्वपूर्ण नोट: सभी कुंजी अद्वितीय हैं और सभी मान अद्वितीय हैं। इस जानकारी के साथ मैं महसूस करता हूं.TryGetValue और ओ (एन) .TryGetKey के लिए ओ (1) की तुलना में बेहतर समय में इस कार्य को पूरा करना संभव होना चाहिए।

संपादित करें:

मेरे मामले में, मैं strings और ints के बीच एक मैपिंग की है। ग्रंथों और उनकी आईडी के ~ 650,000 कुंजी-मूल्य जोड़े हैं। इसलिए मैं मूल रूप से एक विशिष्ट आईडी के साथ स्ट्रिंग प्राप्त करना चाहता हूं लेकिन एक निश्चित स्ट्रिंग की आईडी भी प्राप्त करना चाहता हूं।

+0

"स्मृति को डुप्लिकेट किए बिना (इसलिए दो शब्दकोष प्रश्न से बाहर हैं)।" दो शब्दकोशों का उपयोग करके स्मृति को डुप्लिकेट नहीं किया जाता है जब तक कि आपका 'टीकेई' और 'टीवील्यू' दोनों स्ट्रक्चर नहीं होते हैं। –

+0

@ScottChamberlain वे दोनों structs हैं :) –

+0

मुझे नहीं पता कि आप क्या पूछना संभव है। मेरा मतलब है, मुझे बहुत कुछ पता नहीं है और अभी भी सीखने के लिए बहुत कुछ है लेकिन कंप्यूटर विज्ञान के बारे में मैंने हमेशा एक बात सुनी है: "आप इसे तेजी से चाहते हैं? आपको स्मृति चाहिए। आप इसे हल्का चाहते हैं? यह धीमा हो जाएगा।" लेकिन जब मैं घुसपैठ कर रहा हूं, तो मैं आपके प्रश्न का पक्ष लेता हूं। –

उत्तर

-2

आप ऐसी चीज कर सकते हैं;

Dictionary<string, string> types = new Dictionary<string, string>() 
      { 
         {"1", "one"}, 
         {"2", "two"}, 
         {"3", "three"} 
      }; 

      var myValue = types.FirstOrDefault(x => x.Value == "one").Key; 
+3

'शब्दकोश .FirstOrDefault()' 'ओ (एन)', 'ओ (1) 'नहीं है। – CodeCaster

+1

मुझे नहीं पता कि यह टिप्पणी मेरा उत्तर देने के लिए थी, लेकिन देखें [विकिपीडिया: बिग ओ नोटेशन] (https://en.wikipedia.org/wiki/Big_O_notation)। – CodeCaster

+0

क्षमा करें, यह गलत है, इसे गलत पढ़ें – Ktt

0

आप जो करना चाहिए value के लिए value आवरण और आवरण जो चाहिए key आवरण के लिए मूल्य और लिंक होता है के लिए महत्वपूर्ण और लिंक होता है key के लिए कुछ आवरण लिख सकते हैं। और दो अलग HashSet एस का उपयोग करें।
इस मामले में आप स्मृति डुप्लिकेटिंग से बचें। आपको लिंक के लिए केवल अतिरिक्त मेमोरी चाहिए।

3

ओ (एन) से बेहतर होने के लिए आपको 2 शब्दकोश का उपयोग करने की आवश्यकता होगी। हालांकि जैसा कि आपने बताया है कि आप structs का उपयोग कर रहे हैं और एक दूसरी शब्दकोश के साथ मेमोरी उपयोग के बारे में चिंतित हैं जिसमें संरचना की डुप्लिकेट प्रति है।

इसके आस-पास एक तरीका ऑब्जेक्ट के अंदर संरचना मूल्य बॉक्स है, फिर बॉक्सिंग ऑब्जेक्ट को दो शब्दकोशों में साझा करें। यदि आप DictionaryBase से उत्तराधिकारी का उपयोग करते हैं तो यह वास्तव में लागू करने में काफी आसान है।

public sealed class TwoWayDictionary<TKey, TValue> : DictionaryBase 
{ 
    Hashtable reverseLookup = new Hashtable(); 

    public void Add(TKey key, TValue value) 
    { 
     this.Dictionary.Add(key, value); 
    } 

    public void Remove(TKey key) 
    { 
     this.Dictionary.Remove(key); 
    } 

    public bool TryGetValue(TKey key, out TValue value) 
    { 
     object lookup = Dictionary[key]; 
     if (lookup == null) 
     { 
      value = default(TValue); 
      return false; 
     } 
     else 
     { 
      value = (TValue)lookup; 
      return true; 
     } 
    } 

    public bool TryGetKey(TValue value, out TKey key) 
    { 
     object lookup = reverseLookup[value]; 
     if (lookup == null) 
     { 
      key = default(TKey); 
      return false; 
     } 
     else 
     { 
      key = (TKey)lookup; 
      return true; 
     } 
    } 

    //If OnInsertComplete or OnSetComplete raises a exception DictionaryBase will 
    // roll back the operation it completed. 
    protected override void OnInsertComplete(object key, object value) 
    { 
     reverseLookup.Add(value, key); 
    } 

    protected override void OnSetComplete(object key, object oldValue, object newValue) 
    { 
     if(reverseLookup.Contains(newValue)) 
      throw new InvalidOperationException("Duplicate value"); 
     if(oldValue != null) 
      reverseLookup.Remove(oldValue); 
     reverseLookup[newValue] = key; 
    } 

    protected override void OnRemoveComplete(object key, object value) 
    { 
     reverseLookup.Remove(value); 
    } 
} 

Dictionary और reverseLookup शब्दकोशों ही संदर्भ का हिस्सा तो यह दृढ़ता से टाइप किया दो शब्दकोशों का उपयोग कर बड़े structs के साथ तुलना में एक छोटे स्मृति पदचिह्न होगा।

एक पूर्ण Dictionary<TKey, TValue> कार्यान्वयन लिखने के बिना जो कुंजी और मूल्यों के लिए दो आंतरिक बाल्टी संग्रह और बाल्टी के चेन के लिए दो लिंक्ड सूचियों का उपयोग करता है, मुझे नहीं लगता कि आपको बेहतर परिणाम मिल सकते हैं।

+0

यह एक अच्छा समाधान है जब दोWayDictionary रनटाइम पर बनाया गया है, लेकिन अब मैं सोच रहा हूं ... क्या वास्तव में प्रदर्शन को बनाए रखने, इसे क्रमबद्ध और deserialized किया जा सकता है? –

+0

@Randolph यह होना चाहिए, आपको केवल '[Serializeable]' विशेषता डालना है और यह अच्छा होना चाहिए। 'डिक्शनरीबेस' और 'हैशटेबल' दोनों को पहले से ही क्रमबद्ध के रूप में चिह्नित किया गया है। लेकिन आपको इसका परीक्षण करने की आवश्यकता होगी। यदि यह एक नया सवाल पूछने में स्वतंत्र नहीं है कि यह क्यों विफल हो रहा है यदि आप इसे समझ नहीं सकते हैं। –

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