2015-04-15 14 views
6

Supponiamo di avere un tipo di struttura in Vai che desidero utilizzare come chiave in una mappa, ma I non desidera utilizzare l'operazione di uguaglianza integrata di Go. Qual è il modo migliore per costruire una mappa del genere?Vai mappa con chiave definita dall'utente con uguaglianza definita dall'utente?

Per un esempio concreto, ecco la mia chiave di tipo e l'uguaglianza di funzionamento:

type Key struct { 
    a *int 
} 

func Equal(x Key, y Key) bool { 
    return *x.a == *y.a 
} 

Come posso costruire una mappa che utilizza Equal per il confronto chiave?

+0

Ma come dovrei dichiarare che la mappa dovrebbe usare quel metodo? Peggio ancora, nel mio vero codice, il campo a è una porzione di int e, per quanto ne so, non ci sono operazioni di uguaglianza integrate per i silenti. –

+0

Sì nelle FAQ https://golang.org/doc/faq c'è una domanda per "perché le mappe non consentono le porzioni come chiavi" e la risposta è che non esiste un operatore di uguaglianza integrato. Ho proposto quella che penso sia la soluzione più ragionevole nella mia risposta. – evanmcdonnal

risposta

2

Questo non è possibile in Go. Non esiste un overloading dell'operatore o un metodo 'Equaluality' che puoi sovrascrivere (a causa di non ereditare da una classe base comune come in .NET che il tuo esempio mi ricorda). Questa risposta ha più informazioni sui confronti di uguaglianza se sei interessato; Is it possible to define equality for named types/structs?

Come menzionato nei commenti se si desidera realizzare qualcosa come questo, si consiglia di utilizzare una proprietà sull'oggetto come chiave. È possibile definire l'uguaglianza in base a come si imposta il valore di tale proprietà (come potrebbe essere un checksum dei byte degli oggetti o qualcosa del genere se si sta cercando l'uguaglianza dei membri).

6

Go ha strict comparable semantics for values used as map keys. Di conseguenza, non è possibile definire il proprio codice hash e le funzioni di uguaglianza per le chiavi della mappa, come è possibile in molte altre lingue.

Tuttavia, considerare la seguente soluzione alternativa. Invece di usare le istanze struct direttamente come chiavi, usa un attributo derivato della struct che è intrinsecamente utilizzabile come chiave e ha la semantica dell'uguaglianza che desideri. Spesso è semplice ricavare un intero o un valore stringa come un codice hash che funge da identità per un'istanza.

Ad esempio:

type Key struct { 
    a *int 
} 

func (k *Key) HashKey() int { 
    return *(*k).a 
} 

k1, k2 := Key{intPtr(1)}, Key{intPtr(2)} 
m := map[int]string{} 
m[k1.HashKey()] = "one" 
m[k2.HashKey()] = "two" 
// m = map[int]string{1:"one", 2:"two"} 
m[k1.HashKey()] // => "one" 

Naturalmente, immutabilità è una preoccupazione critica con questo approccio. Nell'esempio sopra, se modifichi il campo a, l'istanza non può più essere utilizzata come chiave hash perché la sua identità è cambiata.

+0

Grazie. Nel mio codice reale ho le fette come le chiavi. Credo che dovrò usare un hash di altissima qualità a 128 bit, o "cancellarli" con le stringhe. –

+0

@ ArchD.Robison: certo, il builtin ['pacchetto crypto/md5'] (http://golang.org/pkg/crypto/md5/) potrebbe essere utile per questo, o anche una semplice rappresentazione in formato stringa della slice tramite [ 'fmt.Sprintf ("% v", SLC)'] (http://golang.org/pkg/fmt/#Sprintf). – maerics

Problemi correlati