在golang中用零替换数字

时间:2015-07-13 08:39:14

标签: regex string algorithm replace go

我想用零替换字符串中的所有数字,理想情况下连续数字应替换为一个零。
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字符串时仍然非常慢,并且它不能很好地替换连续数字。
有没有更好的方法呢?

2 个答案:

答案 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