2011-01-25 15 views
7

मैं यूनियन शब्दकोष (प्रकार के शब्दकोश) में विलय करने के लिए विधि का परीक्षण कर रहा हूं। यह टीवीएलयू प्रकार स्ट्रिंग या इंट या ऑब्जेक्ट के साथ ठीक काम करता है। लेकिन अगर टीवीएयू प्रकार एक संग्रह है (सूची और वस्तु [] के साथ परीक्षण किया गया है) एक अपवाद फेंक दिया गया है: "ArgumentException: एक ही कुंजी वाला एक आइटम पहले ही जोड़ा जा चुका है।" क्यों व्यवहार समान नहीं हैशब्दकोश को मर्ज करें <TKey, TValue> Enumerable.Union विधि

Dictionary<int,string> _dico1 = new Dictionary<int, string>() 
{ 
    {0, "zero"}, 
    {1, "one"} 
}; 

Dictionary<int,string> _dico2 = new Dictionary<int,string>() 
{ 
    {1 , "one"}, 
    {2 , "two"}, 
    {3 , "three"}, 
    {4 , "four"}, 
    {5 , "five"}, 
    {6 , "six"} 
}; 

Dictionary<int, List<string>> _dico3 = new Dictionary<int, List<string>>() 
{ 
    {0, new List<string>{"zero"}}, 
    {1, new List<string>{"one"}} 
}; 

Dictionary<int, List<string>> _dico4 = new Dictionary<int, List<string>>() 
{ 
    {1, new List<string>{"one"}}, 
    {2, new List<string>{"two"}}, 
    {3, new List<string>{"three"}}, 
    {4, new List<string>{"four"}}, 
    {5, new List<string>{"five"}}, 
    {6, new List<string>{"six"}}, 
}; 

    // works fine 
    var mergeDico = _dico1.Union(_dico2).ToDictionary(key => key.Key, value => value.Value); 

    // throw an ArgumentException : An item with the same key has already been added 
    var mergeDico2 = _dico3.Union(_dico4).ToDictionary(key => key.Key, value => value.Value); 

:

यहाँ मेरी कोड है? और इस समस्या को कैसे हल करें?

धन्यवाद!

उत्तर

7

पहले मामले में, संघ डुप्लिकेट कुंजी को छोड़ रहा है क्योंकि कुंजी/मूल्य जोड़े स्वयं बराबर हैं। दूसरे मामले में वे नहीं हैं, क्योंकि List<String>{"one"} किसी अन्य List<string>{"one"} के बराबर नहीं है।

मुझे संदेह है कि आप Union को IEqualityComparer का उपयोग करने के लिए कॉल करना चाहते हैं जो केवल शब्दकोश के भीतर कुंजी का खाता लेता है।

+0

तो, पहले मामले में, यह काम करता है क्योंकि TValue प्रकार मान प्रकार (int) कर रहे हैं या अपरिवर्तनीय प्रकार (स्ट्रिंग) और, दूसरे मामले में यह विफल रहता है क्योंकि टीवीएला संदर्भ प्रकार है? – Florian

+5

@ फ्लोरियन: यह अपरिवर्तनीयता के कारण सीधे नहीं है - यह इस बात के कारण है कि इसमें शामिल प्रकारों की समानता अर्थशास्त्र है। आप अभी भी अपरिवर्तनीय प्रकार कर सकते हैं जो ऐसा नहीं करते हैं। –

2

आप इस तरह के कोड के साथ शब्दकोशों की दूसरी जोड़ी विलय कर सकते हैं:

 

var mergeDico2 = _dico3 
    .Concat(_dico4) 
    .GroupBy(_=> _.Key, _ => _.Value) 
    .ToDictionary(
     group => group.Key, 
     group => group.SelectMany(_ => _).ToList()); 
 

यह एक नया शब्दकोश जहां प्रत्येक मान दोनों शब्दकोशों के मूल्यों से सूचियों श्रृंखलाबद्ध का परिणाम है का उत्पादन करेगा। आप सूचियों का केवल विशिष्ट तत्वों की जरूरत है तो आप इस एक के लिए ToDictionary कॉल बदल सकते हैं:

 

var mergeDico2 = _dico3 
    .Concat(_dico4) 
    .GroupBy(_=> _.Key, _ => _.Value) 
    .ToDictionary(
     group => group.Key, 
     group => group.SelectMany(_ => _).Distinct().ToList()); 
 
1

जॉन पहले से ही उल्लेख किया है कि हम ऊपर समस्या को हल करने IEqualityComparer को लागू करने की जरूरत है।

IEqualityComparer:: यहाँ कोड है कि यह कैसे किया जा सकता है

public class MyEqualityComparer : IEqualityComparer<KeyValuePair<int,List<string>>> 
{ 
    public bool Equals(KeyValuePair<int, List<string>> x, KeyValuePair<int, List<string>> y) 
    { 
     //Let's say we are comparing the keys only. 
     return x.Key == y.Key; 
    } 

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

उपयोग:

Dictionary<int, List<string>> _dico3 = new Dictionary<int, List<string>>() 
    { 
     {0, new List<string> {"zero"}}, 
     {1, new List<string> {"one"}} 
    }; 

Dictionary<int, List<string>> _dico4 = new Dictionary<int, List<string>>() 
    { 
     {1, new List<string> {"one"}}, 
     {2, new List<string> {"two"}}, 
     {3, new List<string> {"three"}}, 
     {4, new List<string> {"four"}}, 
     {5, new List<string> {"five"}}, 
     {6, new List<string> {"six"}}, 
    }; 

Dictionary<int, List<string>> mergeDico2 = _dico3.Union(_dico4, new MyEqualityComparer()) 
    .ToDictionary(x => x.Key, x => x.Value); 
संबंधित मुद्दे