472,121 Members | 1,486 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,121 software developers and data experts.

C# Duplicate key error in Dictionary with List<int> type key

Hello,
I am trying to create a dictionary item with its key as list type and value as custom object type. It gives me a error
"An item with the same key has already been added."

Here is my code:

Expand|Select|Wrap|Line Numbers
  1. List<int> Pkey = new List<int>();
  2. Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>();
  3. // initialize A with last column.
  4. for (int r = 0; r < n; ++r)
  5. {
  6.     Pkey.Clear();
  7.     Pkey.Add(r);
  8.     A.Add(Pkey, m.GetElement(r, n - 1));
  9. }
where m.GetElement(r, n - 1) returns a Polynomial type object.

Please help me out. I'm stuck.
Nov 19 '08 #1
15 18475
r035198x
13,262 8TB
You do realize from your code that you have created only one list?
Nov 19 '08 #2
Creating one List means? ... if you are saying about 1 item in the list, then the code is fine as it is of some use to me later in the code
Nov 19 '08 #3
nukefusion
221 Expert 100+
To elaborate, you are only creating one list object: PKey. You then try to add that same object (PKey) to the Keys collection of your dictionary object A on each iteration of the loop.

Each object added to A's keys collection must be unique.

To fix your code you'd need to move the list declaration to inside the loop

Expand|Select|Wrap|Line Numbers
  1. Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
  2. // initialize A with last column. 
  3. for (int r = 0; r < n; ++r) 
  4.     List<int> Pkey = new List<int>();
  5.     Pkey.Add(r); 
  6.     A.Add(Pkey, m.GetElement(r, n - 1)); 
Nov 19 '08 #4
thanks nukefusion.
it helped

To elaborate, you are only creating one list object: PKey. You then try to add that same object (PKey) to the Keys collection of your dictionary object A on each iteration of the loop.

Each object added to A's keys collection must be unique.

To fix your code you'd need to move the list declaration to inside the loop

Expand|Select|Wrap|Line Numbers
  1. Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
  2. // initialize A with last column. 
  3. for (int r = 0; r < n; ++r) 
  4.     List<int> Pkey = new List<int>();
  5.     Pkey.Add(r); 
  6.     A.Add(Pkey, m.GetElement(r, n - 1)); 
Nov 19 '08 #5
Plater
7,872 Expert 4TB
It should be noted that since you are using an object as a key, you will not be able to create another List<int> with the exact same values contained within, and use it as a key.
Nov 19 '08 #6
nukefusion
221 Expert 100+
It should be noted that since you are using an object as a key, you will not be able to create another List<int> with the exact same values contained within, and use it as a key.
I don't think that's the case. As far as I know, the Dictionary collection uses the Equals() method to determine key equality.
In the case of a generic list of integers, it is the object reference that determines equality. Therefore, as long as the lists are not the same object, it doesn't matter whether or not the numbers inside the list are the same.

I tested it to be sure and I can add two integer lists containing just the number 1 to a dictionary with no exception.
Nov 19 '08 #7
Plater
7,872 Expert 4TB
Isn't that what I just said?
Nov 19 '08 #8
nukefusion
221 Expert 100+
Isn't that what I just said?
No, you said:
you will not be able to create another List<int> with the exact same values contained within, and use it as a key.
...which is incorrect because you can. Just didn't want there to be any confusion.
Nov 19 '08 #9
Plater
7,872 Expert 4TB
Oh ok I see the confusion.
I ment you couldn't create that list and then use it as the key to retrieve a value from a list with the same contents.
Nov 19 '08 #10
I tried the method you suggested but now there is another problem.
I created a dictionary item with different lists. But now when I try to retrieve the dictionary value using some other list as key which contains the same list items (integers) which is present in the dictionary, it gives me error that no such key exists.
I think its because dictionary is storing reference of the List and and not its values.

But now I'm again stuck. Please suggest me some solution.
Nov 19 '08 #11
Plater
7,872 Expert 4TB
I think its because dictionary is storing reference of the List and and not its values.
Yup, thats just what we were discussing.
Why do you need to use multiple ints as a key?
Nov 19 '08 #12
I am using it for some advanced mathematical calculations.
In actual scenario, a group of numbers in a particular sequence refer to some polynomial object. And it goes bit more complex if I explain it here.

The List which is used to insert the dictionary item and the list which is used to retrieve dictionary value are being generated from different sources. So I'm facing this problem.
Nov 19 '08 #13
Plater
7,872 Expert 4TB
Create a unique string from the List<int> ?
if your list contains:
4356
2467
23534
1
45

Then your string could be:
4356-2467-23534-1-45

And you would use a Dictionary<string, polynomial>
You could even wrap the Dictionary class or whatever to provide a
public polynomial Get(List<int>)

Where you would build the string from a given List<int> and return the polynomial from the dictionary
Nov 19 '08 #14
nukefusion
221 Expert 100+
Ah, I see where you were going now Plater. :)

One method to fix your new problem would be Platers suggestion, which should work well.
Alternatively, you could also thinly wrap List<int> and override the Equals() and GetHashCode() methods. I've chucked together a bit of code for you:

Expand|Select|Wrap|Line Numbers
  1.  public class MyIntCollection : List<int>
  2.     {
  3.         public override bool Equals(object obj)
  4.         {
  5.             MyIntCollection collection2 = (MyIntCollection)obj;
  6.  
  7.             if (collection2.Count != this.Count) return false;
  8.             for (int i = 0; i < this.Count; i++)
  9.             {
  10.                 if (this[i] != collection2[i]) return false;
  11.             }
  12.             return true;
  13.         }
  14.  
  15.         public override int GetHashCode()
  16.         {
  17.             int hashCode = 0;
  18.             for (int i = 0; i < this.Count; i++)
  19.             {
  20.                 hashCode = hashCode ^ this[i];
  21.             }
  22.             return hashCode;
  23.         }
  24.     }
You could then use this class in place of your List<int>. like so:
Expand|Select|Wrap|Line Numbers
  1.         Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
  2.         // initialize A with last column. 
  3.         for (int r = 0; r < n; ++r) 
  4.         { 
  5.             MyIntCollection PKey = new MyIntCollection(); 
  6.             Pkey.Add(r); 
  7.             A.Add(Pkey, m.GetElement(r, n - 1)); 
  8.         } 
Using this method, two seperate lists containing the same numbers (in the same sequence) are considered equal, regardless of whether or not they are the same reference. Trying to add two different MyIntCollection objects containing the same sequence of numbers to the dictionary fails.

You can modify the code of Equals() to determine whether two MyIntCollections are equal to suit your requirements. GetHashCode() is required by the Dictionary class to ensure that keys are unique. It must return the same value for objects where Equals() returns true. You can look these up on MSDN for more info if required.
Nov 19 '08 #15
Thanks a lot to both of you.
I believe the solutions provided will solve my problem.
Thanks again. :)
Nov 19 '08 #16

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

2 posts views Thread by John Dalberg | last post: by
2 posts views Thread by deathtospam | last post: by
1 post views Thread by Monty | last post: by
1 post views Thread by Danny Ni | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.