2011-04-06 4 views
18

मैं एक शब्दकोश वस्तु बना रहा हूं, IEnumerable के ToDictionary() विस्तार विधि का उपयोग कर:आपको डुप्लिकेट कुंजी कैसे मिलती है जो ToDictionary() विफल हो गई है?

एक ही कुंजी के साथ एक आइटम पहले से ही किया गया है:

var dictionary = new Dictionary<string, MyType> 
    (myCollection.ToDictionary<MyType, string>(k => k.Key)); 

जब वह निष्पादित निम्नलिखित ArgumentException फेंकता जोड़ा।

मुझे यह बताने के लिए कैसे मिलता है कि डुप्लिकेट कुंजी क्या है?

+2

यह आपके प्रश्न का उत्तर नहीं है, लेकिन ToDictionary वास्तव में एक शब्दकोश बनाता है। आप उस शब्दकोश को किसी अन्य शब्दकोश के निर्माता में क्यों गुजर रहे हैं? और जेनेरिक टाइप पैरामीटर निर्दिष्ट क्यों नहीं करते हैं? मैं उस सामान के बिना अपना उदाहरण लिखूंगा: 'var dictionary = myCollection.ToDictionary (x => x.Key);' –

+0

1. क्योंकि यह शब्दकोश के लिए कन्स्ट्रक्टर ओवरलोड में से एक है। लेकिन आपके पास एक बिंदु है। –

+0

2. संभवतः, प्रकार निर्दिष्ट करना मुक्केबाजी की किसी भी संभावना को समाप्त करता है, लेकिन मुझे इसके बारे में निश्चित नहीं है। –

उत्तर

16

डुप्लिकेट चाबी प्राप्त करें:

var duplicateKeys = 
    myCollection 
.GroupBy(k => k.Key) 
.Where(g => g.Count() > 1) 
.Select(g => g.Key); 
+2

अजीब लगता है कि 'ToDictionary()' द्वारा फेंक दिया गया 'ArgumentException' विफल कुंजी शामिल नहीं है। आपकी क्वेरी कितनी महंगा है? संग्रह बहुत बड़ा है। –

+0

@ रॉबर्ट हार्वे, वास्तव में यह बिल्कुल सामान्य है: 'ArgumentException' एक बहुत ही सामान्य अपवाद है, यह शब्दकोशों के लिए विशिष्ट नहीं है ... –

+0

@ रॉबर्ट हार्वे: समूहिंग काफी कुशल है, लेकिन एक बड़े संग्रह के साथ यह निश्चित रूप से अभी भी होगा बहुत सारा काम। इसे 'डिक्शनरी ' का उपयोग करके अधिक कुशलतापूर्वक किया जा सकता है और केवल उन्हें समूहित करने के बजाय प्रत्येक कुंजी की घटनाओं की गणना कर सकते हैं। – Guffa

5

में विफल रहा है कुंजी शामिल नहीं है क्योंकि सामान्य शब्दकोश कोई गारंटी नहीं है कि वहाँ कुंजी प्रकार पर एक सार्थक ToString विधि है। आप एक रैपर वर्ग बना सकते हैं जो अधिक जानकारीपूर्ण अपवाद फेंकता है। उदाहरण के लिए:

//Don't want to declare the key as type K because I assume _inner will be a Dictionary<string, V> 
//public void Add(K key, V value) 
// 
public void Add(string key, V value) 
{ 
    try 
    { 
     _inner.Add(key, value); 
    } 
    catch (ArgumentException e) 
    { 
     throw new ArgumentException("Exception adding key '" + key + "'", e); 
    } 
} 
+0

यह एक दिलचस्प विचार है। –

+0

मुझे हस्ताक्षर 'शून्य जोड़ें (स्ट्रिंग कुंजी, वी मान) बनाना चाहिए था क्योंकि मेरा सुझाव मानता है कि आप केवल स्ट्रिंग कुंजी में रूचि रखते हैं। उत्तर संपादित किया गया। – phoog

+0

('क्योंकि जेनेरिक डिक्शनरी की कोई गारंटी नहीं है ...' उसे गारंटी की आवश्यकता क्यों होगी?) – Iain

1

ArgumentExceptionDictionary.Add करने के लिए कॉल द्वारा फेंका जा रहा है महत्वपूर्ण मूल्य शामिल नहीं है। आप बहुत आसानी से एक शब्दकोश अपने आप से प्रविष्टियां जोड़ सकते हैं, और पहले से एक अलग जांच:

var dictionary = new Dictionary<string, MyType>(); 
    foreach (var item in myCollection) 
    { 
     string key = item.Key; 
     if (dictionary.ContainsKey(key)) 
     { 
      // Handle error 
      Debug.Fail(string.Format("Found duplicate key: {0}", key)); 
     } 
     else 
     { 
      dictionary.Add(key, item); 
     } 
    } 

इस अतिरिक्त जांच काफी सस्ती होना चाहिए क्योंकि तत्वों हैश द्वारा जमा हो जाती है।

+0

हाँ, यह सच है। मुझे लगता है कि मैं सिर्फ 'ToDictionary()' विधि के साथ आलसी था। –

+0

शब्दकोश। जोड़ें कहते हैं कि यह एक डुप्लिकेट कुंजी पर फेंकता है। तो आप सीधे (सीधे) जोड़कर प्रदर्शन लाभ प्राप्त कर सकते हैं और इसे फेंकने पर पकड़ कर सकते हैं। – Iain

+2

उद्देश्य पर अपवाद को पकड़ना लगभग हमेशा एक बुरा विचार प्रदर्शन के रूप में होता है, अपवाद फेंकना और पकड़ना इतना जटिल है कि आप अधिकतर समय अतिरिक्त जांच जोड़कर प्रदर्शन में सुधार करेंगे। –

8

अपने विशिष्ट स्थिति यह केवल आपके शब्दकोश में डुप्लिकेट Key गुणों के साथ वस्तुओं का एक सेट में से एक डालने के लिए ठीक करता है, तो आप पहले ToDictionary बुला लिए LINQ Distinct विधि का उपयोग कर पूरी तरह से इस त्रुटि से बचने कर सकते हैं।

var dict = myCollection.Distinct().ToDictionary(x => x.Key); 
बेशक

, ऊपर केवल तभी कार्य करेगा अपने संग्रह ओवरराइड Equals और GetHashCode एक तरीका है कि केवल खाते में Key संपत्ति लेता में में कक्षाएं। यदि ऐसा नहीं है, तो आपको कस्टम IEqualityComparer<YourClass> बनाना होगा जो केवल Key संपत्ति की तुलना करता है।

var comparer = new MyClassKeyComparer(); 
var dict = myCollection.Distinct(comparer).ToDictionary(x => x.Key); 

आप यह सुनिश्चित करें कि अपने संग्रह में सभी उदाहरणों शब्दकोश में समाप्त, तो Distinct का उपयोग कर आप के लिए काम नहीं करेगा बनाने के लिए की जरूरत है।

+0

धन्यवाद, मेरी स्थिति का एक सही समाधान – PandaWood

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