我试图编写一个函数,它返回一个不重复的字符串中的查找第一个字符,到目前为止,我有这个:
package main
import (
"fmt"
"strings"
)
func check(s string) string {
ss := strings.Split(s, "")
smap := map[string]int{}
for i := 0; i < len(ss); i++ {
(smap[ss[i]])++
}
for k, v := range smap {
if v == 1 {
return k
}
}
return ""
}
func main() {
fmt.Println(check("nebuchadnezzer"))
}
不幸的是,当你迭代一张地图时,我不保证顺序,所以每次运行代码时我得到一个不同的值,任何指针?
答案 0 :(得分:4)
使用地图和2个循环:
play
func check(s string) string {
m := make(map[rune]uint, len(s)) //preallocate the map size
for _, r := range s {
m[r]++
}
for _, r := range s {
if m[r] == 1 {
return string(r)
}
}
return ""
}
如果您使用strings.ContainsRune
,strings.IndexRune
(每个函数将在其中包含内部循环),这样做的好处是仅使用2个循环与多个循环。
答案 1 :(得分:1)
用于获取所有或第一个唯一字节http://play.golang.org/p/ZGFepvEXFT的高效(时间和内存)算法:
func FirstUniqueByte(s string) (b byte, ok bool) {
occur := [256]byte{}
order := make([]byte, 0, 256)
for i := 0; i < len(s); i++ {
b = s[i]
switch occur[b] {
case 0:
occur[b] = 1
order = append(order, b)
case 1:
occur[b] = 2
}
}
for _, b = range order {
if occur[b] == 1 {
return b, true
}
}
return 0, false
}
作为奖励,上述功能永远不会产生任何垃圾。请注意,我将您的功能签名更改为表达您所描述内容的更惯用的方式。如果你还需要func(string) string
签名,那么这一点就没有实际意义了。
答案 2 :(得分:0)
这肯定可以优化,但一个解决方案(不使用地图)将是:
(playground example)
func check(s string) string {
unique := ""
for pos, c := range s {
if strings.ContainsRune(unique, c) {
unique = strings.Replace(unique, string(c), "", -1)
} else if strings.IndexRune(s, c) == pos {
unique = unique + string(c)
}
}
fmt.Println("All unique characters found: ", unique)
if len(unique) > 0 {
_, size := utf8.DecodeRuneInString(unique)
return unique[:size]
}
return ""
}
这是在问题&#34; Find the first un-repeated character in a string&#34;
之后返回包含第一个完整符文的字符串,而不仅仅是第一个符文的utf8编码的第一个字节。