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);
精彩评论