Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary<int [], bool> - compare values in the array, not reference?

I am using dictionary for storing ID,otherID and bool value. Unfortunately it compares array reference, therefore I cannot use it. Is there any way how to have an array as key but compare its values instead of reference? Thanks

like image 410
Snake Avatar asked Jan 07 '10 08:01

Snake


4 Answers

You can use the Comparer property of the dictionary to set it to a custom comparer created by you.

EDIT: actually the property is read-only, sorry. You should definitely use the proper constructor:

class IntArrayComparer : 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 ret = 0;
        for (int i = 0; i < obj.Length; ++i) {
            ret ^= obj[i].GetHashCode();
        }
        return ret;
    }
}
static void Main(string[] args) {
    Dictionary<int[], bool> dict = new Dictionary<int[], bool>(new IntArrayComparer());
}
like image 152
Paolo Tedesco Avatar answered Sep 29 '22 07:09

Paolo Tedesco


You can try implementing IEqualityComparer<int[]> and then pass an instance of it to the proper constructor.

like image 45
Darin Dimitrov Avatar answered Sep 29 '22 08:09

Darin Dimitrov


There are basically two ways of doing that:

  • Create a comparer that implements IEqualityComparable<int[]>, that you pass to the constructor of the dictionary.
  • Create a key class that encapsulates the integer array and implements IEquatable<T>.
like image 22
Guffa Avatar answered Sep 29 '22 07:09

Guffa


There's nothing wrong with orsogufo's answer, but I wanted to point out that if you have .NET 3.5, you can implement an ArrayValueComparer with a lot less code, and at the same time make it generic, so it can compare the values of any type of array, and not just integer arrays. For that matter, you could easily make it work with any IEnumerable, and not just arrays.

using System.Collections.Generic;
using System.Linq;

class ArrayValueComparer<T> : IEqualityComparer<T[]>
{
    public bool Equals(T[] x, T[] y)
    {
        return x.SequenceEqual(y, EqualityComparer<T>.Default);
    }

    public int GetHashCode(T[] obj)
    {
        return obj.Aggregate(0, (total, next) => total ^ next.GetHashCode());
    }
}

static void Main(string[] args)
{
    var dict = new Dictionary<int[], bool>(new ArrayValueComparer<int>());
}
like image 32
Joel Mueller Avatar answered Sep 29 '22 08:09

Joel Mueller