Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashing an array in c#

Tags:

arrays

c#

.net

hash

Short question

How to implement GetHashCode for an Array.

Details

I have an object that overrides Equals, checking that:

this.array[n] == otherObject.array[n]

for all n in array.

Naturally I should implement the complementary GetHashCode. I was wondering if there is .NET way to do this, or if I should implement my own, something like

hash = hash ^ array[n]

Clarification

My object contains an array, and I'm interested on GetHashCode for the elements of the array. My code for array equivalence is for example only - like my question says but maybe I wasn't clear, I'm interested in GetHashCode (not Equals). I say I naturally should implement the complementary GetHashCode because it is a requirement of .NET to implement this once Equals is overridden (for Dictionary etc. to function correctly). Thanks.

like image 432
c z Avatar asked May 09 '16 14:05

c z


People also ask

Can I hash an array?

Python Hashing (Hash tables and hashlib) While an array can be used to construct hash tables, array indexes its elements using integers. However, if we want to store data and use keys other than integer, such as 'string', we may want to use dictionary. Dictionaries in Python are implemented using hash tables.

What are hashes in C?

A Hash Table in C/C++ (Associative array) is a data structure that maps keys to values. This uses a hash function to compute indexes for a key. Based on the Hash Table index, we can store the value at the appropriate location.

Can we use Hashmap in C?

Generally you create an array called "buckets" that contain the key and value, with an optional pointer to create a linked list. When you access the hash table with a key, you process the key with a custom hash function which will return an integer.

What is the hash function in array?

A hash function maps each key to an integer in the range [0, N -1], where N is the capacity of the bucket array for the hash table. The main idea is to use the hash value, h(k), as an index into our bucket array, A, instead of the key k (which is most likely inappropriate for use as a bucket array index).


2 Answers

To compute a hash code using the elements of an array, you can cast the array to IStructuralEquatable and then call the GetHashCode(IEqualityComparer) method, passing a comparer for the type of elements in the array.

(The cast is necessary because the Array class implements the method explicitly.)

For example, if your object has an int array, then you can implement GetHashCode like this:

public override int GetHashCode() {     return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default); } 

In case you're curious, here's how the Array class implements the GetHashCode method (from the Reference Source):

internal static int CombineHashCodes(int h1, int h2) {     return (((h1 << 5) + h1) ^ h2); }  int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {     if (comparer == null)         throw new ArgumentNullException("comparer");     Contract.EndContractBlock();      int ret = 0;      for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {         ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i)));     }      return ret; } 

As you can see, the current implementation only uses the last eight elements of the array.

like image 156
Michael Liu Avatar answered Oct 17 '22 04:10

Michael Liu


It depends on what you want ...

One option as Michael answered above is to have a hashcode based on the array elements. This will be in line with your Equals value semantics. However because "As a guideline, the hash of an object must be the same over the object's entire lifetime" you will have to ensure your array does not change after getting its hashcode. To have a non immutable container with a demand that it never changes sounds error prone to me.

Your other (IMO better option) is to switch to an immutable container (ie ImmutableArray) then a value-based hashcode makes sense. You can either use IStructuralEquatable as above or more generally:

    public override GetHashCode() =>
        Value.Aggregate(0, (total, next) => HashCode.Combine(total, next));

which will work for other immutable collections as well.

like image 42
kofifus Avatar answered Oct 17 '22 03:10

kofifus