2014-05-05 16 views
19

Sono nuovo di Golang e ora voglio ottenere un oggetto arbitrario da una mappa, qual è il modo più idiomatico per farlo? Posso solo pensare di STH come di seguito:Ottieni una chiave/elemento arbitrario da una mappa

func get_some_key(m map[int]int) int { 
    for k := range m { 
      return k 
    } 
    return 0 
} 

Il motivo che voglio che sia sto usando una mappa di mantenere una serie di posti di lavoro e con una mappa che posso ottenere un lavoro in attesa o di rimuovere un lavoro finito a O (1). Immagino che questo dovrebbe essere un requisito comune ma non è ovvio farlo in giro.

Grazie in anticipo!

+1

Conosci il valore della chiave che stai cercando di ottenere o impostare o stai cercando di trovare una chiave casuale o una chiave che non conosci in anticipo? – dethtron5000

+0

Stai cercando la chiave che ha un valore particolare? Se stai solo cercando il valore associato a un tasto è semplicemente 'm [i]'. –

+1

Il tuo approccio sembra buono. Se è possibile accedere simultaneamente alla mappa da due goroutine, proteggere l'operazione di recupero/eliminazione con un 'sync.Mutex' in modo che due goroutine non catturino lo stesso lavoro (e poiché le mappe sono, per motivi di velocità, non intrinsecamente thread-safe) . – twotwotwo

risposta

12

È possibile discutere se ottenere una chiave arbitraria da una tabella hash è un requisito comune. L'implementazione di altre mappe è spesso priva di questa funzionalità (ad esempio Dictionary in C#)

Tuttavia, la soluzione è probabilmente la più veloce, ma rimarrai con un algoritmo pseudo-casuale che non controlli. E mentre il momento implementazione utilizza un algoritmo di pseduo-casuale, il Go Specification non ti dà alcuna rassicurazione sarà effettivamente essere casuale, ma solo che non è garantito per essere prevedibile:

L'ordine iterazione su mappe non è specificato e non è garantito che sia lo stesso da una iterazione alla successiva.

Se si desidera un maggiore controllo della randomizzazione, è possibile anche in parallelo tenere un fetta aggiornata di valori (o chiavi) contenuti nella mappa, utilizzando la randomizzazione di vostra scelta (math/rand o crypto/rand per i casi più estremi) per ottenere il valore memorizzato in un indice, selezionato casualmente, nella sezione.

+0

Grazie per la tua risposta, per favore vedi il mio commento sopra, non ho bisogno di alcun controllo sulla randomizzazione, voglio solo un modo che "dammi solo un elemento dalla mappa" se ce ne sono. – chuchao333

+1

@ chuchao333 Quindi la soluzione è buona. Un altro modo simile è 'var k, v int; per k, v = range m {break} 'se vuoi farlo in linea. E per assicurarti di avere un valore, puoi fare: 'var k, v int; var ok bool; per k, v = range m {ok = true; break} ' – ANisus

+0

Cosa intendi per" ottenere un indice dalla sezione "nell'ultima frase? – jochen

1

Ottenere una chiave casuale da una mappa comporta solo un secondo contatore come un numero casuale.

// choices = map[string]... 

i := rand.Intn(len(choices)) 
var k string 
for k = range choices { 
    if i == 0 { 
    break 
    } 
    i-- 
} 

fmt.Println(k, choices[k]) 

La mappa può avere qualsiasi tipo di chiave valida e solo bisogno di cambiare var k string da abbinare. Puoi raggrupparlo come una funzione:

func randIntMapKey(m map[int]string) int { 
    i := rand.Intn(len(m)) 
    for k := range m { 
     if i == 0 { 
      return k 
     } 
     i-- 
    } 
    panic("never") 
} 
Problemi correlati