我想用零替换字符串中的所有数字,理想情况下连续数字应替换为一个零。
abc826def47
应该成为abc0def0
我尝试了两种方法:
使用正则表达式:
var numbersRegExp = regexp.MustCompile("[0-9]+")
func normalizeNumbers(str string) string{
return numbersRegExp.ReplaceAllString(str, "0")
}
使用strings.Replace
import s "strings"
func normalizeNumbers(str string) string{
str = s.Replace(str, "1", "0", -1)
str = s.Replace(str, "2", "0", -1)
str = s.Replace(str, "3", "0", -1)
str = s.Replace(str, "4", "0", -1)
str = s.Replace(str, "5", "0", -1)
str = s.Replace(str, "6", "0", -1)
str = s.Replace(str, "7", "0", -1)
str = s.Replace(str, "8", "0", -1)
str = s.Replace(str, "9", "0", -1)
str = s.Replace(str, "00", "0", -1)
return str
}
不使用正则表达式的第二种方法似乎要快一点,但在使用大约100k字符串时仍然非常慢,并且它不能很好地替换连续数字。
有没有更好的方法呢?
答案 0 :(得分:6)
最快的解决方案是(始终)即时构建输出。这需要循环输入的符文一次,并使用适当的初始输出“缓冲区”(在这种情况下为[]rune
),您还可以避免重新分配。
以下是实施:
func repNums(s string) string {
out := make([]rune, len(s)) // len(s) is bytes not runes, this is just estimation
i, added := 0, false
for _, r := range s {
if r >= '0' && r <= '9' {
if added {
continue
}
added, out[i] = true, '0'
} else {
added, out[i] = false, r
}
i++
}
return string(out[:i])
}
测试:
fmt.Printf("%q\n", repNums("abc826def47")) // "abc0def0"
fmt.Printf("%q\n", repNums("1234")) // "0"
fmt.Printf("%q\n", repNums("asdf")) // "asdf"
fmt.Printf("%q\n", repNums("")) // ""
fmt.Printf("%q\n", repNums("a12b34c9d")) // "a0b0c0d"
在Go Playground上尝试。
备注:强>
len(s)
不是输入的符文数,而是字节数。这是一个较高的估计,但不需要任何努力。如果您愿意,可以使用utf8.RuneCountInString()
来获取输入string
中的符文的确切数量(但这会对输入string
的符文进行解码和循环,而不是真的值得)。 r >= '0' && r <= '9'
的数字。或者,您可以使用unicode.IsDigit()
string
(这是不可变的)。答案 1 :(得分:1)
您可以使用 regexp 软件包:
t := "abc826def47"
re := regexp.MustCompile(`\d`)
r := re.ReplaceAllString(t, "0")
这将使您abc000def00
脱离abc826def47
。