2010-04-12 16 views
31

मैं कोड के विभिन्न टुकड़ों के लिए इस तरह कोड के ब्लॉक करने का बीमार हूँ मैं:.net शब्दकोश और देखने जोड़ें/अपडेट करें

if (dict.ContainsKey[key]) { 
    dict[key] = value; 
} 
else { 
    dict.Add(key,value); 
} 

और लुकअप के लिए (यानी कुंजी -> मूल्य की सूची)

if (lookup.ContainsKey[key]) { 
    lookup[key].Add(value); 
} 
else { 
    lookup.Add(new List<valuetype>); 
    lookup[key].Add(value); 
} 

क्या कोई अन्य संग्रह lib या एक्सटेंशन विधि है जिसका उपयोग मुझे कोड की एक पंक्ति में करने के लिए करना चाहिए चाहे कोई भी कुंजी और मूल्य प्रकार न हों?

उदा।

dict.AddOrUpdate(key,value) 
lookup.AddOrUpdate(key,value) 
+0

'लुकअप' '' ILookup 'है? मैं ऐसा नहीं सोच रहा क्योंकि इसमें 'ContainsKey' विधि नहीं होनी चाहिए। प्रश्न पूछने के बाद बस .NET ने लुकअप को नहीं बदला है, क्योंकि 'ILookup' को अपडेट करने का कोई तरीका ढूंढ रहा था ... – drzaus

उत्तर

32

एव्जेनी कहते हैं, इंडेक्सर पहले से ही विद्यमान मूल्यों को बदल देगा - तो आप सिर्फ बिना शर्त किसी कुंजी के लिए मान सेट करना चाहते हैं, आप कर सकते हैं

dictionary[key] = value; 

अधिक दिलचस्प मामला "मूल्य प्राप्त करें, या यदि आवश्यक हो तो इसे सम्मिलित करें"। यह एक विस्तार विधि के साथ क्या करना आसान है:

public static TValue GetOrCreateValue<TKey, TValue> 
    (this IDictionary<TKey, TValue> dictionary, 
    TKey key, 
    TValue value) 
{ 
    return dictionary.GetOrCreateValue(key,() => value); 
} 

public static TValue GetOrCreateValue<TKey, TValue> 
    (this IDictionary<TKey, TValue> dictionary, 
    TKey key, 
    Func<TValue> valueProvider) 
{ 
    TValue ret; 
    if (!dictionary.TryGetValue(key, out ret)) 
    { 
     ret = valueProvider(); 
     dictionary[key] = ret; 
    } 
    return ret; 
} 

नोट एक प्रतिनिधि के उपयोग डिफ़ॉल्ट मान बनाने के लिए - यह है कि एक "मूल्य के रूप में सूची" की तरह परिदृश्यों की सुविधा; - एक ContainsKey और फिर देखो करने के लिए कोई आवश्यकता नहीं है

dict.GetOrCreateValue(key,() => new List<int>()).Add(item); 

यह भी ध्यान रखें कि यह कैसे सिर्फ एक बार देखने प्रदर्शन करती है, तो कुंजी पहले से मौजूद है: यदि आप नहीं है खाली सूची बनाने के लिए जब तक आप प्राप्त करना चाहते हैं मूल्य ऊपर। यद्यपि यह नया मान बना रहा है, फिर भी इसे दो लुकअप की आवश्यकता है।

1

इम यकीन नहीं अगर वहाँ एक तरीका है की तरह आप के लिए पूछना है, लेकिन आप कोशिश पकड़ अपवाद इसके लिए एक छोटे से समारोह लिखते हैं, या इस्तेमाल कर सकते हैं, शायद आप मान पहले से मौजूद है कि यह फेंक जाएगा जोड़ने का प्रयास करें एक अपवाद। यदि आप इसे पकड़ते हैं और इसे अनदेखा करते हैं ... बस एक सुझाव

4

.NET 4.0 में ConcurrentDictionary this nice method है। आप इसके लिए एक विस्तार विधि भी लिख सकते हैं।

14

आपको अपडेट करते समय आपको चेक करने की आवश्यकता नहीं है। बस उपयोग करें:

dict[key] = value 

यह किसी मौजूदा मान को प्रतिस्थापित करेगा। दुर्भाग्यवश मूल्य को पुनर्प्राप्त करते समय कोई सुविधाजनक एकल विधि नहीं है (जैसे setdefault पायथन में), लेकिन आप अपनी खुद की विस्तार विधि बना सकते हैं। कुछ इस तरह:

if (!lookup.TryGetValue(key, out value)) 
{ 
    value = new List<T>(); 
    lookup.Add(key, value); 
} 
3

.NET फ्रेमवर्क 4 या बाद में साथ काम कर रहे हैं, तो आप AddOrUpdate Method

dict.AddOrUpdate(key,value) 

जोड़ने या अपडेट उपयोग कर सकते हैं इस

dict[key] = value; 
+4

यह केवल' ConcurrentDictionary' – Mrchief

+0

के लिए उपलब्ध है हां, आप इसे समवर्ती शब्दकोश के साथ उपयोग करते हैं क्योंकि आप ' टी एक जाल में गिरना चाहता है जहां आप अतिरिक्त स्थिति की जांच करते हैं, यह निर्धारित करते हैं कि आपको एक ऐड करने की ज़रूरत है, फिर अपनी पीठ के पीछे कुछ और करें। AddOrUpdate इसे परमाणु बनाता है, मुझे विश्वास है। – quillbreaker

0

की तरह है मैं AddOrUpdateConcurrentDictionary की विधि की तरह है, लेकिन मैं प्रदर्शन की तरह शब्दकोश संग्रह का भी :) तो, यह IDictionary लागू करने वाले सभी वर्गों के लिए विस्तार विधि है।

public static TValue AddOrUpdate<TKey, TValue>(
    this IDictionary<TKey, TValue> dict, 
    TKey key, 
    TValue addValue, 
    Func<TKey, TValue, TValue> updateValueFactory) 
{ 
    TValue existing; 
    if (dict.TryGetValue(key, out existing)) 
    { 
     addValue = updateValueFactory(key, existing); 
     dict[key] = addValue; 
    } 
    else 
    { 
     dict.Add(key, addValue); 
    } 

    return addValue; 
} 


public static TValue AddOrUpdate<TKey, TValue>(
    this IDictionary<TKey, TValue> dict, 
    TKey key, 
    Func<TKey, TValue> addValueFactory, 
    Func<TKey, TValue, TValue> updateValueFactory) 
{ 
    TValue existing; 
    if (dict.TryGetValue(key, out existing)) 
    { 
     existing = updateValueFactory(key, existing); 
     dict[key] = existing; 
    } 
    else 
    { 
     existing = addValueFactory(key); 
     dict.Add(key, existing); 
    } 

    return existing; 
} 
संबंधित मुद्दे