我想要一个键不敏感的字符串作为键。 它是由语言支持还是我必须自己创建? 谢谢
编辑我正在寻找的是一种默认设置方法,而不必每次使用地图时都记得转换密钥。
答案 0 :(得分:10)
编辑:我的初始代码实际上仍允许映射语法,因此允许绕过这些方法。这个版本更安全。
你可以“派生”一种类型。在Go我们只是说声明。然后在类型上定义方法。它只需要一个非常薄的包装器来提供您想要的功能。但请注意,必须使用普通方法调用语法调用get和set。没有办法保持内置映射的索引语法或可选的ok结果。
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)
}
答案 1 :(得分:3)
两种可能性:
如果输入集保证仅限制为转换为大写/小写将产生正确结果的字符(对于某些Unicode字符可能不正确),则转换为大写/小写
否则转换为Unicode折叠案例:
使用unicode.SimpleFold(rune)
将unicode符文转换为折叠大小写。显然,这比简单的ASCII风格的案例映射更加昂贵,但它对其他语言也更具可移植性。请参阅the source code for EqualsFold以了解如何使用它,包括如何从源字符串中提取Unicode符文。
显然,您将此功能抽象到一个单独的包中,而不是在使用地图的任何地方重新实现它。这应该是不言而喻的,但是你永远不会知道。
答案 2 :(得分:0)
这里有一些比 strings.ToLower 更强大的东西,你可以使用 golang.org/x/text/cases 包。示例:
package main
import "golang.org/x/text/cases"
func main() {
s := cases.Fold().String("March")
println(s == "march")
}
如果你想使用标准库中的东西,我运行了这个测试:
package main
import (
"strings"
"unicode"
)
func main() {
var (
lower, upper int
m = make(map[string]bool)
)
for n := '\u0080'; n <= '\u07FF'; n++ {
q, r := n, n
for {
q = unicode.SimpleFold(q)
if q == n { break }
for {
r = unicode.SimpleFold(r)
if r == n { break }
s, t := string(q), string(r)
if m[t + s] { continue }
if strings.ToLower(s) == strings.ToLower(t) { lower++ }
if strings.ToUpper(s) == strings.ToUpper(t) { upper++ }
m[s + t] = true
}
}
}
println(lower == 951, upper == 989)
}
因此可以看出,ToUpper
是稍微更好的选择。