Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a case insensitive map in Go?

I want to have a key insensitive string as key. Is it supported by the language or do I have to create it myself? thank you

Edit: What I am looking for is a way to make it by default instead of having to remember to convert the keys every time I use the map.

like image 782
Santiago Corredoira Avatar asked Jun 20 '12 17:06

Santiago Corredoira


People also ask

Is Go Language case-sensitive?

The name of the identifier is case sensitive. Keywords is not allowed to use as an identifier name. There is no limit on the length of the name of the identifier, but it is advisable to use an optimum length of 4 – 15 letters only.

How do you make a Golang map?

Using make function: You can also create a map using make() function. This function is an inbuilt function and in this method, you just need to pass the type of the map and it will return an initialized map.] Example: Go.

How do you compare String case-insensitive in Golang?

In Golang string are UTF-8 encoded. strings package of GO provides an EqualFold method that can be used to do case insensitive comparison of two strings in Go. Below is the signature of the function. The methods return boolean indicating whether the two strings supplied are case insensitive equal or not.


2 Answers

Edit: My initial code actually still allowed map syntax and thus allowed the methods to be bypassed. This version is safer.

You can "derive" a type. In Go we just say declare. Then you define methods on your type. It just takes a very thin wrapper to provide the functionality you want. Note though, that you must call get and set with ordinary method call syntax. There is no way to keep the index syntax or optional ok result that built in maps have.

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)
}
like image 158
Sonia Avatar answered Oct 04 '22 04:10

Sonia


Two possiblities:

  1. Convert to uppercase/lowercase if you're input set is guaranteed to be restricted to only characters for which a conversion to uppercase/lowercase will yield correct results (may not be true for some Unicode characters)

  2. Convert to Unicode fold case otherwise:

Use unicode.SimpleFold(rune) to convert a unicode rune to fold case. Obviously this is dramatically more expensive an operation than simple ASCII-style case mapping, but it is also more portable to other languages. See the source code for EqualsFold to see how this is used, including how to extract Unicode runes from your source string.

Obviously you'd abstract this functionality into a separate package instead of re-implementing it everywhere you use the map. This should go without saying, but then you never know.

like image 38
tylerl Avatar answered Oct 04 '22 04:10

tylerl