开发者

Array comprasion as Dictionary keys in C#

I want to create class representing n-dimensional array, but where is a commutative access to its elements. e.g: a[new[] {4, 7, 55}] == a[new[] {55, 4, 7}]

I write this code, where I implement interface IEqualityComparer in order to compare keys (which are arrays) by their real content, but not refs.

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

class NArray
{
    public int this[int[] x]
    {
        get
        {
            Array.Sort(x);
            return array[x];
        }
        set
        {
            Array.Sort(x);
            array[x] = value;
        }
    }

    public void Remove(int[] x)
    {
        Array.Sort(x);
        array.Remove(x);
    }

    Dictionary<int[], int> array = new Dictionary<int[], int>(new ArrCmpr());
}

class ArrCmpr : IEqualityComparer<int[]>
{
    public bool Equals(int[] a, int[] b)
    {
        return a.Length == b.Length && Enumerable.Range(0, a.Length).All(i => a[i] == b[i]);
    }

    public int GetHashCode(int[] a)
    {
        return a.GetHashCode();
    }
}

But when I start to use this class I encounter an exception: "System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary." This exception occurs in next both cases when I try to output the element to console:

NArray a = new NArray();
a[new[] { 1, 3, 2 }] = 4;

Console.WriteLine(a[new[] { 3, 2, 1 }]); //error

 

NArray b = new NArray();
b[new[] { 1, 2, 3 }] = 4;
Console.WriteLine(b[new[] { 1, 2, 3 }]);    //error

So what is the cause of that problem a开发者_JS百科nd how could I fix it?


That's because your implementation of GetHashCode is incorrect: two different arrays with the same items in the same order usually won't have the same hashcode (because the values are not taken into account), so Equals is never called.

You need an implementation of GetHashCode that takes the values in the array into account:

class ArrCmpr : IEqualityComparer<int[]>
{
    public bool Equals(int[] a, int[] b)
    {
        return a.SequenceEqual(b);
    }

    public int GetHashCode(int[] a)
    {
        return a.Aggregate(0, (acc, i) => unchecked(acc * 457 + i * 389));
    }
}


To me seems that GetHashCode have to be changed as it simply returns the hash code of Array object, considering the fact that you use NEW hashcode every time will be different, even if content equal.


Since you're using a Dictionary to store your arrays you need to check if the key exists already, and only then can you access it with the [] operator, otherwise if you try to access a key that doesn't exist an exception is thrown

// your get function
if(array.ContainsKey(x))
    return array[x];
else // do something like return null
    return null;

// your set function
if(array.ContainsKey(x))
    array[x] = value;
else
    array.Add(x, value);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜