29

I wish to have the dictionary which uses an array of integers as keys, and if the integer array has the same value (even different object instance), they will be treated as the same key. How should I do it?

The following code does not work as b is different object instances.

 int[] a = new int[] { 1, 2, 3 };
 int[] b = new int[] { 1, 2, 3 };
 Dictionary<int[], string> dic = new Dictionary<int[], string>();
 dic.Add(a, "haha");
 string output = dic[b];
william007
  • 17,375
  • 25
  • 118
  • 194
  • 1
    Duplicate: http://stackoverflow.com/questions/3383534/dictionary-with-integer-array-as-a-key Kindof it has to do with `List` – Nate-Wilkins Feb 02 '13 at 15:03

3 Answers3

45

You can create an IEqualityComparer to define how the dictionary should compare items. If the ordering of items is relevant, then something like this should work:

public class MyEqualityComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] x, int[] y)
    {
        if (x.Length != y.Length)
        {
            return false;
        }
        for (int i = 0; i < x.Length; i++)
        {
            if (x[i] != y[i])
            {
                return false;
            }
        }
        return true;
    }

    public int GetHashCode(int[] obj)
    {
        int result = 17;
        for (int i = 0; i < obj.Length; i++)
        {
            unchecked
            {
                result = result * 23 + obj[i];
            }
        }
        return result;
    }
}

Then pass it in as you create the dictionary:

Dictionary<int[], string> dic
    = new Dictionary<int[], string>(new MyEqualityComparer());

Note: calculation of hash code obtained here: What is the best algorithm for an overridden System.Object.GetHashCode?

Community
  • 1
  • 1
Glen Hughes
  • 4,712
  • 2
  • 20
  • 25
  • Why there is a need for GetHashCode other than the Equal operator? – william007 Feb 02 '13 at 15:45
  • 3
    @william007 Because a `Dictionary<,>` maintains a hash table of its keys, and therefore it is necessary to have a `GetHashCode` that respects the new `Equals`. For the same reason, the `IEqualityComparer<>` interface requires you to do `GetHashCode`. – Jeppe Stig Nielsen Feb 02 '13 at 15:51
  • 4
    Why do you call it **`My`** `EqualityComparer`? The fact that it's yours is irrelevant. It should be called `IntArrayEqualityComparer` or something similar :) – BartoszKP Mar 22 '14 at 14:52
  • Why can GetHashCode() not simply return obj.GetHashCode()? – Simon Hewitt Jan 18 '18 at 18:52
  • 1
    @SimonHewitt because a hash code must follow the rule that if two objects return true for `x.Equals(y)` then `x.GetHashCode() == y.GetHashCode()` must also be true. Using `obj.GetHashCode()` will not fulfill that promise because you have a custom implementation of `Equals` you will be using for the comparisons so you will end up with `x.Equals(y) == true` and `x.GetHashCode() != y.GetHashCode()` which is illegal in a correct hashcode implementation.. – Scott Chamberlain Oct 28 '18 at 17:03
  • Using an array as a key of the dictionary, Python is faster than C# by about 50-100 times. It is supported by Python out of the box, sadly. – Hieu Le Sep 08 '22 at 04:39
5

Maybe you should consider using a Tuple

var myDictionary = new Dictionary<Tuple<int,int>, string>(); 
myDictionary.Add(new Tuple<int,int>(3, 3), "haha1"); 
myDictionary.Add(new Tuple<int,int>(5, 5), "haha2"); 

According to MSDN , Tuple objects Equals method will use the values of the two Tuple objects

Jaydeep Shil
  • 1,894
  • 22
  • 21
0

The easiest way if you don't care about actual hashing may just be to convert the array into a string. Adding a space to avoid numbers joining.

dic.Add(String.Join(" ",a), "haha");
Community
  • 1
  • 1
Alex
  • 552
  • 3
  • 15
  • 1
    dic.Add(String.Join("", new int[] {1, 2, 3}), "haha"); dic.Add(String.Join("", new int[] {12, 3}), "this fails"); – Paul Childs Apr 26 '21 at 00:29
  • the performance of this approach is not good enough in case using it for memorizing paths in algorithms such as DFS – Hieu Le Sep 08 '22 at 04:30
  • In fact, it is twice slower than https://stackoverflow.com/a/14663233/8012407. However, all the solutions up to now are still significantly slower than Python. – Hieu Le Sep 08 '22 at 04:34