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

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • hsachdevah
    New Member
    • Nov 2008
    • 20

    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:

    Code:
    List<int> Pkey = new List<int>();
    Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>();
    // initialize A with last column.
    for (int r = 0; r < n; ++r)
    {
        Pkey.Clear();
        Pkey.Add(r);
        A.Add(Pkey, m.GetElement(r, n - 1));
    }
    where m.GetElement(r, n - 1) returns a Polynomial type object.

    Please help me out. I'm stuck.
  • r035198x
    MVP
    • Sep 2006
    • 13225

    #2
    You do realize from your code that you have created only one list?

    Comment

    • hsachdevah
      New Member
      • Nov 2008
      • 20

      #3
      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

      Comment

      • nukefusion
        Recognized Expert New Member
        • Mar 2008
        • 221

        #4
        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

        Code:
        Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
        // initialize A with last column. 
        for (int r = 0; r < n; ++r) 
        { 
            List<int> Pkey = new List<int>();
            Pkey.Add(r); 
            A.Add(Pkey, m.GetElement(r, n - 1)); 
        }

        Comment

        • hsachdevah
          New Member
          • Nov 2008
          • 20

          #5
          thanks nukefusion.
          it helped

          Originally posted by nukefusion
          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

          Code:
          Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
          // initialize A with last column. 
          for (int r = 0; r < n; ++r) 
          { 
              List<int> Pkey = new List<int>();
              Pkey.Add(r); 
              A.Add(Pkey, m.GetElement(r, n - 1)); 
          }

          Comment

          • Plater
            Recognized Expert Expert
            • Apr 2007
            • 7872

            #6
            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.

            Comment

            • nukefusion
              Recognized Expert New Member
              • Mar 2008
              • 221

              #7
              Originally posted by Plater
              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.

              Comment

              • Plater
                Recognized Expert Expert
                • Apr 2007
                • 7872

                #8
                Isn't that what I just said?

                Comment

                • nukefusion
                  Recognized Expert New Member
                  • Mar 2008
                  • 221

                  #9
                  Originally posted by Plater
                  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.

                  Comment

                  • Plater
                    Recognized Expert Expert
                    • Apr 2007
                    • 7872

                    #10
                    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.

                    Comment

                    • hsachdevah
                      New Member
                      • Nov 2008
                      • 20

                      #11
                      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.

                      Comment

                      • Plater
                        Recognized Expert Expert
                        • Apr 2007
                        • 7872

                        #12
                        Originally posted by hsachdevah
                        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?

                        Comment

                        • hsachdevah
                          New Member
                          • Nov 2008
                          • 20

                          #13
                          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.

                          Comment

                          • Plater
                            Recognized Expert Expert
                            • Apr 2007
                            • 7872

                            #14
                            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<stri ng, 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

                            Comment

                            • nukefusion
                              Recognized Expert New Member
                              • Mar 2008
                              • 221

                              #15
                              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:

                              Code:
                               public class MyIntCollection : List<int>
                                  {
                                      public override bool Equals(object obj)
                                      {
                                          MyIntCollection collection2 = (MyIntCollection)obj;
                              
                                          if (collection2.Count != this.Count) return false;
                                          for (int i = 0; i < this.Count; i++)
                                          {
                                              if (this[i] != collection2[i]) return false;
                                          }
                                          return true;
                                      }
                              
                                      public override int GetHashCode()
                                      {
                                          int hashCode = 0;
                                          for (int i = 0; i < this.Count; i++)
                                          {
                                              hashCode = hashCode ^ this[i];
                                          }
                                          return hashCode;
                                      }
                                  }
                              You could then use this class in place of your List<int>. like so:
                              Code:
                                      Dictionary<List<int>, Polynomial> A = new Dictionary<List<int>, Polynomial>(); 
                                      // initialize A with last column. 
                                      for (int r = 0; r < n; ++r) 
                                      { 
                                          MyIntCollection PKey = new MyIntCollection(); 
                                          Pkey.Add(r); 
                                          A.Add(Pkey, m.GetElement(r, n - 1)); 
                                      }
                              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 MyIntCollection s 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.

                              Comment

                              Working...