2010-10-25 5 views
17

मैं सी # लक्ष्यीकरण .NET 3.5 में एक ऐप विकसित कर रहा हूं। इसमें, मेरे पास 2 समान शब्दकोश हैं जिनमें मेरे ऐप में तत्वों के विशिष्ट सेट के लिए सत्यापन मानदंड शामिल हैं। दोनों शब्दकोशों में समान हस्ताक्षर होते हैं। पहले शब्दकोश में डिफ़ॉल्ट सेटिंग्स होती हैं और दूसरे शब्दकोश में कुछ उपयोगकर्ता परिभाषित सेटिंग्स होती हैं।सी # विलय 2 शब्दकोश

var default_settings = new Dictionary<string, MyElementSettings>(); 
var custom_settings = new Dictionary<string, MyElementSettings>(); 

मैं 2 शब्दकोशों को एक साथ जोड़ना चाहता हूं जिसमें दोनों शब्दकोशों के तत्व शामिल हैं।

जिस समस्या में मैं चल रहा हूं, यह है कि दोनों शब्दकोशों में से कुछ समान मूल्यों के लिए संभव है। मूल नियम जो मैं चाहता हूं वह दोनों शब्दकोशों का संयोजन होना है और यदि कस्टम_सेटिंग में पहले से मौजूद डिफ़ॉल्ट_सेटिंग में कोई कुंजी है, तो custom_settings मान डिफ़ॉल्ट_सेटिंग मान को ओवरराइट कर देगा। मेरे पास सबसे अच्छा समाधान सिर्फ एक फोरच लूप है, जांचें कि कुंजी अन्य शब्दकोश में मौजूद है या नहीं, और यदि नहीं, तो इसे जोड़ें।

foreach (var item in custom_settings) 
{ 
    if (default_settings.ContainsKey(item.Key)) 
     default_settings[item.Key] = item.Value; 
    else 
     default_settings.Add(item.Key, item.Value); 
} 

मैं कुछ बुनियादी LINQ प्रश्नों किया है, लेकिन मैं अभी भी और अधिक उन्नत सामान सीखने पर काम कर रहा हूँ। मैंने कुछ प्रश्नों को देखा है जो 2 शब्दकोशों को मर्ज करेंगे, लेकिन अधिकांश में डुप्लिकेट कुंजियों के साथ किसी भी तत्व को समूहीकृत करना शामिल है, या केवल डुप्लिकेट कुंजी के साथ संग्रह को वापस लेना/क्या कोई LINQ क्वेरी या अभिव्यक्ति है जो फ़ोरैच लूप के व्यवहार की नकल करेगी मै इस्तेमाल कर रहा हूँ?

उत्तर

38

दो अंक:

  1. LINQ दुष्प्रभाव को क्रियान्वित करने के लिए महान नहीं है। इस मामले में, आप किसी क्वेरी को निष्पादित करने के बजाए मौजूदा संग्रह को म्यूटेट करने का प्रयास कर रहे हैं, इसलिए मैं एक शुद्ध LINQ समाधान से दूर शर्मिंदा हूं।
  2. setter on the generic dictionary's indexer कुंजी कुंजी मान जोड़ी मौजूद है, या तो अगर कुंजी मौजूद है तो ओवर-वैल्यू जोड़ी जोड़ने का प्रभाव पहले से ही है।

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

foreach (var item in custom_settings) 
{ 
    default_settings[item.Key] = item.Value; 
} 

अब जब कि पहले से ही बहुत संक्षिप्त है, तो मुझे नहीं लगता कि LINQ सब है कि आप बहुत मदद करने के लिए जा रहा है है:

तो अपने foreach पाश अनिवार्य रूप से करने के लिए बराबर है।

+3

बिंदु # 2 (http://msdn.microsoft.com/en-us/library/k7z0zy8k.aspx) – Brad

+1

+1 मुझे कुछ मुझे नहीं पता था कि शिक्षण के लिए लिए +1। मैं अपेक्षाकृत स्वयं सी # के साथ सिखाया जाता हूं और कभी नहीं जानता था कि आप शब्दकोशों के साथ ऐसा कर सकते हैं। – psubsee2003

+0

@ psubsee2003: चीयर्स। मुझे पूरा यकीन है कि मैंने आपके कोड के समान पैटर्न का इस्तेमाल किया था इससे पहले कि मैंने पाया कि यह अनावश्यक था (मौके से, परावर्तक के साथ घूम रहा था)। – Ani

2

अपने इस एक बहुत क्या करने जा रहा है, तो मैं शब्दकोश चाबी के लिए एक समानता comparer लेखन की सलाह देते हैं:

private class KeyEqualityComparer<T, U> : IEqualityComparer<KeyValuePair<T, U>> 
{ 
    public bool Equals(KeyValuePair<T, U> x, KeyValuePair<T, U> y) 
    { 
     return x.Key.Equals(y.Key); 
    } 

    public int GetHashCode(KeyValuePair<T, U> obj) 
    { 
     return obj.Key.GetHashCode(); 
    } 
} 

और फिर जब भी आप शब्दकोशों मर्ज करने के लिए की जरूरत है, आप कर सकते हैं निम्नलिखित

var comparer = new KeyEqualityComparer<string, MyElementSettings>(); 
dict1 = dict1.Union(dict2,comparer).ToDictionary(a => a.Key, b => b.Value); 
+0

यह मेरे लिए काम करता है, यहां तक ​​कि 'KeyEqualityComparer' वर्ग/पैरामीटर के बिना भी। धन्यवाद – AceMark

1

मुझे लगता है कि मूल रूप से मैंने जो उत्तर चुना है, वह अभी भी इस विशेष मामले के लिए सबसे अच्छा जवाब है, मुझे थोड़ी देर पहले एक और इसी तरह की स्थिति में मिला, जहां मेरे पास 2 IEnumerable<> ऑब्जेक्ट्स थे जिन्हें मैं एक शब्दकोश में परिवर्तित करना और एक साथ विलय करना चाहता था एक समान फैशन इसलिए मैंने सोचा कि मैं भविष्य में किसी की मदद के लिए यहां उस समाधान को जोड़ दूंगा।दोनों को एक शब्दकोश में परिवर्तित करने और चयनित उत्तर में विधि का उपयोग करने के बजाय, मुझे एक नया दृष्टिकोण मिला।

मैंने वास्तव में एसई-कोड समीक्षा पर initial solution पोस्ट किया और वास्तव में इसे और परिशोधित करने के लिए एक सुझाव दिया था। यहाँ अंतिम कोड मैं प्रयोग किया जाता है:

public Dictionary<String, Foo> Merge(XElement element1, XElement element2) 
{ 
    IEnumerable<Foo> firstFoos = GetXmlData(element1); // parse 1st set from XML 
    IEnumerable<Foo> secondFoos = GetXmlData(element2); // parse 2nd set from XML 

    var result = firstFoos.Union(secondFoos).ToDictionary(k=>k.Name, v=>v); 

    return result; 
} 

public class Foo 
{ 
    public String Name { get; } 

    // other Properties and Methods 
    // . 
    // . 
    // . 

    public override Boolean Equals(Object obj) 
    { 
     if (obj is Foo) 
     { 
      return this.Name == ((Foo)obj).Name;    
     } 

     return false; 
    } 
} 

इस के लिए महत्वपूर्ण Equals() है Foo ओवरराइड चाहिए क्या Foo वस्तुओं डुप्लिकेट माना जा सकता है, और सदस्यों को बताया कि परिभाषित जो वस्तुओं डुप्लिकेट हैं भी Dictionary<> कुंजी होना चाहिए परिभाषित करने के लिए (में इस मामले Name)

आप Foo में Equals() ओवरराइड नहीं कर सकते, तो दूसरा विकल्प Concat() और GroupBy()Union()

012 के बजाय का उपयोग करने के लिए है
public Dictionary<String, Foo> Merge(XElement element1, XElement element2) 
{ 
    IEnumerable<Foo> firstFoos = GetXmlData(element1); // parse 1st set from XML 
    IEnumerable<Foo> secondFoos = GetXmlData(element2); // parse 2nd set from XML 

    var result = firstFoos.Concat(secondFoos) 
          .GroupBy(foo => foo.Name) 
          .Select(grp => grp.First()) 
          .ToDictionary(k=>k.Name, v=>v); 

    return result; 
} 
8

यहां एनी के उत्तर के आधार पर एक अच्छी विस्तार विधि है।

public static class DictionaryExtensionMethods 
{ 
    public static void Merge<TKey, TValue>(this Dictionary<TKey, TValue> me, Dictionary<TKey, TValue> merge) 
    { 
     foreach (var item in merge) 
     { 
      me[item.Key] = item.Value; 
     } 
    } 
} 
+1

मैं IDictionary –

+0

पर शब्दकोश बदलूंगा यदि यह एक शब्दकोश संग्रह 'आईनेमेरेबल <शब्दकोश >' उनसे कैसे मिलान कर सकता है? – barteloma