2012-06-20 6 views
11

Voglio avere una chiave non sensibile come chiave. È supportato dalla lingua o devo crearlo da solo? grazieCome creare una mappa senza distinzione tra maiuscole e minuscole in Go?

Edit: Quello che sto cercando è un modo per rendere di default, invece di dover ricordare per convertire le chiavi ogni volta che uso la mappa.

+1

Eseguire la mappatura su piegatrice Unicode ogni volta, manualmente. – tchrist

+0

SCL, sei interessato con Unicode in questo caso? Cioè, le tue esigenze includono il rifiuto di punti di codice Unicode inaspettati o un'attenta attenzione alla gestione dei punti di codice Unicode previsti? – Sonia

+0

@sonia, ciao, stavo considerando solo ASCII. Ma dal momento che stai chiedendo, come gestirò Unicode? –

risposta

10

Modifica: il mio codice iniziale in realtà consentiva ancora la sintassi della mappa e quindi consentiva l'esclusione dei metodi. Questa versione è più sicura.

È possibile "derivare" un tipo. In Go diciamo semplicemente di dichiarare. Quindi definisci i metodi sul tuo tipo. Basta un involucro molto sottile per fornire la funzionalità desiderata. Nota, però, che devi chiamare get e impostare con la sintassi di chiamata del metodo ordinario. Non c'è modo di mantenere la sintassi dell'indice o il risultato ok opzionale che hanno le mappe incorporate.

package main 

import (
    "fmt" 
    "strings" 
) 

type ciMap struct { 
    m map[string]bool 
} 

func newCiMap() ciMap { 
    return ciMap{m: make(map[string]bool)} 
} 

func (m ciMap) set(s string, b bool) { 
    m.m[strings.ToLower(s)] = b 
} 

func (m ciMap) get(s string) (b, ok bool) { 
    b, ok = m.m[strings.ToLower(s)] 
    return 
} 

func main() { 
    m := newCiMap() 
    m.set("key1", true) 
    m.set("kEy1", false) 
    k := "keY1" 
    b, _ := m.get(k) 
    fmt.Println(k, "value is", b) 
} 
+7

Il mapping in lettere minuscole non funziona per i dati Unicode, solo per ASCII. Qui dovresti eseguire il mapping a foldcase Unicode, non in lettere minuscole. Altrimenti il ​​vostro è un compito di Sisifo, dal momento che il minuscolo di 'Σίσυφος' è' σίσυφος', mentre il minuscolo del suo carattere maiuscolo, 'ΣΊΣΥΦΟΣ', è il corretto' σίσυφοσ', che è davvero il ripiegamento di tutti quelli. Adesso capisci perché Unicode ha una mappa separata? Le casemappings sono troppo complesse per mappare ciecamente a tutto ciò che non è progettato per quello scopo esplicito, e quindi la presenza di una quarta casemap nelle tabelle del case Unicode: maiuscolo, titlecase, minuscolo, foldcase. – tchrist

+0

Non è FUD, @Sonia, è un dato di fatto. Non è possibile utilizzare Unicode in lettere maiuscole o minuscole per verificare il caso in modo insensibile. Il case Unicode è troppo complicato per questo, e non ha nulla a che fare con la normalizzazione. La casemapping semplice e completa è sufficiente a dimostrare il difetto intrinseco: 'toLower (ΣΊΣΥΦΟΣ)' e 'toLower (Σίσυφος)' non sono uguali nonostante le corrispondenze tra maiuscole e minuscole degli originali degli originali. È necessario utilizzare foldcase in Unicode. Il tuo codice è quindi bacato e non soddisfa i requisiti indicati. – tchrist

+3

Il requisito era stringhe. Go usa Unicode per le stringhe, non ASCII. Hanno chiesto una mappa insensibile alle maiuscole e minuscole. Hai fornito una soluzione solo ASCII senza preoccuparti della sera per dirlo. I miei commenti sono perfettamente in argomento, perché non hai risposto alla domanda come chiesto e formulato, che non aveva restrizioni solo ASCII. Ora, si scopre che questa persona in realtà non aveva nient'altro che ASCII, e quindi la tua soluzione è svanita anche se nel caso generale è sbagliato. Scrivi soluzioni che funzionano per Unicode e funzioneranno anche per ASCII, ma il contrario non regge, motivo per cui il tuo codice è bacato. – tchrist

3

Due possiblities:

  1. Converti in maiuscolo/minuscolo se sei set di input è garantito per essere limitato ai soli caratteri per i quali una conversione in maiuscolo/minuscolo produrrà risultati corretti (non può essere vero per alcuni caratteri Unicode)

  2. Convertire in Unicode caso piega diversa:

Usa unicode.SimpleFold(rune) al c onvertire una runa unicode per piegare il caso. Ovviamente questa operazione è decisamente più costosa di una semplice mappatura di casi in stile ASCII, ma è anche più portabile ad altre lingue. Vedere the source code for EqualsFold per vedere come viene utilizzato, incluso come estrarre le rune Unicode dalla stringa sorgente.

Ovviamente si astraggono questa funzionalità in un pacchetto separato invece di re-implementarlo ovunque si usi la mappa. Questo dovrebbe essere ovvio, ma non lo saprai mai.

+0

Ma questo potrebbe essere soggetto a errori perché forse è esposto come una biblioteca o posso dimenticare di farlo. C'è un modo per creare un tipo derivato che possa farlo automaticamente? –

+5

Questo è completamente sbagliato. ** Devi * usare * le regole di piegatura delle maiuscole Unicode. ** Considera che 'S',' s' e 's' sono tutti equivalenti senza distinzione tra maiuscole e minuscole, come anche' Σ', 'ς' e' σ'. Inoltre, 'TSCHÜSS',' TSCHÜẞ', 'tschüß',' tschüss' sono tutti ugualmente insensibili al caso. Non puoi fare ciò che fingi, mappando tutto a tutti i caratteri maiuscoli o minuscoli. Questo semplicemente non funziona. – tchrist

+2

Funziona bene se sai che hai a che fare solo con ASCII, che potrebbe essere il suo caso d'uso. –

Problemi correlati