2012-12-11 13 views
7

Sto provando a pensare a un modo per ignorare GetHashCode() quando chiamato da Vector2 []. Questo codice produce hash non univoci per oggetti che so essere uguali: passo la classe seguente allo stesso rettangolo e vengono generati diversi codici hash.Come hash un int [] in C#

public Shape(Rectangle r) 
     { 
      edges = new Vector2[4]; 
      edges[0] = new Vector2(0, 0); 
      edges[1] = new Vector2(r.Width, 0); 
      edges[2] = new Vector2(r.Width, r.Height); 
      edges[3] = new Vector2(0, r.Height); 
      Console.Write(edges.GetHashCode() + "\n"); 
      Position = new Vector2(r.X, r.Y);     
     } 

Un array Vector2 è solo un mucchio di ints. Come posso creare un hash univoco per un elenco di ints?

+0

Questo potrebbe dovrebbe funzionare. Puoi pubblicare un esempio completo che mostra due vettori uguali che producono diversi codici hash? –

+1

Gli array non forniscono un codice hash basato sul contenuto dell'array .. quindi questo codice non funzionerà. È necessario eseguire il rollover, oppure se si utilizza .NET 4, utilizzare [Interfaccia IStructuralEquatable] (http://msdn.microsoft.com/en-us/library/system.collections.istructuralequatable.aspx). –

+0

@SimonWhitehead: Davvero? Quindi cosa restituisce [Vector2.GetHashCode] (http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector2.gethashcode%28v=xnagamestudio.10%29.aspx)? –

risposta

4

si può usare qualcosa di simile:

public static int CombineHashCodes(params int[] hashCodes) 
{ 
    if (hashCodes == null) 
    { 
     throw new ArgumentNullException("hashCodes"); 
    } 

    if (hashCodes.Length == 0) 
    { 
     throw new IndexOutOfRangeException(); 
    } 

    if (hashCodes.Length == 1) 
    { 
     return hashCodes[0]; 
    } 

    var result = hashCodes[0]; 

    for (var i = 1; i < hashCodes.Length; i++) 
    { 
     result = CombineHashCodes(result, hashCodes[i]); 
    } 

    return result; 
} 

private static int CombineHashCodes(int h1, int h2) 
{ 
    return (h1 << 5) + h1^h2; 

    // another implementation 
    //unchecked 
    //{ 
    // var hash = 17; 

    // hash = hash * 23 + h1; 
    // hash = hash * 23 + h2; 

    // return hash; 
    //} 
} 
+0

Quindi, esegue il ciclo attraverso un array di due interi alla volta, portando un totale che è spostato di bit di cinque per ogni iterazione e incrementato da solo^il numero successivo. Forse non capisco come funziona il bit shifting, ma non produrrà un numero enorme e massiccio? E dovrei mod fuori dalle dimensioni del mio hash table alla fine? Indipendentemente da ciò, trovo questo utile. –

+2

@MaxKessler No. Usa un "barile hash" in esecuzione (h1 è mescolato con h2) quindi non supera mai la dimensione di un int e * i bit spostati fuori dalla fine vengono rilasciati *. Ricorda che, generalmente, * gli hash non sono (e non possono essere) univoci *; devono essere solo stabili e, si spera, ben distribuiti. –

+0

Capito! Ho cambiato il mio codice in modo che non si utilizzi una collisione come mezzo per identificare se due oggetti sono uguali: ho fatto una piccola ricerca e ho scavalcato il metodo equals sui miei oggetti. Grazie mille! –